New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BulkWrite error :: '$set' is empty. You must specify a field like so: {$set: {<field>: ...}} #293
Comments
The BulkWrite error message you're seeing originates from the server, so I believe this may be an issue higher up the stack. I'll defer to @alcaeus to confirm in alcaeus/mongo-php-adapter#93 first, but I'm happy to investigate if he concludes it's a driver issue. Are you using Doctrine ODM by any chance? The error calls to mind doctrine/mongodb-odm#741, which was something we resolved quite a long time ago for MongoDB 2.6 compatibility. At the time, ODM was prone to creating empty |
We also see this error without Doctrine ODM and according to the stack traces the $set object is definitely not empty Strange is also that we only see these errors on PHP 7 and not PHP 5.6, code base is exactly the same |
According to the trace provided in alcaeus/mongo-php-adapter#93, the call to |
We use the adapter there as well with ext-mongodb, exact same code |
In that case, I'd like to push the ball back to @jmikola and blame mongo-php-driver or mongo-php-library 😁 |
I don't know if it's related but maybe the failing tests Shaked Klein Orbach On Thu, Apr 14, 2016 at 2:24 PM, Andreas notifications@github.com wrote:
|
@Shaked — no, those two ODS test failures are XFAIL: expected failures. |
Hey, I got another update: It seems that, sometimes, although the Another issue I have mentioned in the adapter bug, this also happens with |
The aforementioned ODS tests are being removed in #303. @Shaked: I'm still not having any luck reproducing the issue. I'm attempting to do so with the following script: <pre style="font-size:1em"><?php
define('URI', 'mongodb://192.168.112.10:2000');
define('NS', 'test.foo');
$m = new MongoDB\Driver\Manager(URI);
$cmd = new MongoDB\Driver\Command(['drop' => explode('.', NS)[1]]);
try {
$m->executeCommand(explode('.', NS)[0], $cmd);
} catch (MongoDB\Driver\Exception\RuntimeException $e) {}
$bulk = new MongoDB\Driver\BulkWrite;
$bulk->update(
['_id' => 'req-a10cd3c3-8485-4d21-9928-239379251472'],
['$set' => ['creatorHostname' => 'prod.cloud.net', 'handledAt' => new MongoDB\BSON\UTCDateTime(random_int(0, 999999999))]],
['upsert' => true]
);
$r = $m->executeBulkWrite(NS, $bulk);
printf("nMatched: %d\n", $r->getMatchedCount());
printf("nModified: %d\n", $r->getModifiedCount());
printf("nUpserted: %d\n", $r->getUpsertedCount());
// WriteResult::getUpsertedIds() doesn't handle all ID types (see: PHPC-624)
echo "\n";
$q = new MongoDB\Driver\Query(['_id' => 'req-a10cd3c3-8485-4d21-9928-239379251472']);
$c = $m->executeQuery(NS, $q);
$docs = $c->toArray();
var_dump($docs);
if (count((array) $docs[0]) !== 3) {
fprintf(fopen('php://stderr', 'w'), "Unexpected upsert:\n\n%s\n", var_export($docs[0], true));
} I served this via PHP 7.0.1's built-in web server (e.g. Can you attempt to reproduce using this script, or otherwise tweak it? |
@jmikola Thank you for getting back to me. We have been trying few more things in the last couple of days and I believe it is worth mentioning them in here. Having said that, we are still not sure how to reproduce this error. We have changed an entry in our codebase to directly use the mongo driver without using the php adapter. A side effect of that, ended up with us passing We don't know if the problem is related to the driver or the adapter, therefore we will be testing the same change, changing the adapter to use As well, I have tried to use the example above both with Feel free to ask more question, I would be more than happy to help solving this issue. |
After updating the adapter code by passing
It is worth mentioning that after we pushed the code above to production, and put the server back into load, it took around 30 minutes until errors started to happen. As well, we don't always see these errors, and when we tried it on production ourselves but it didn't fail at all. |
If I understand correctly, the second quote implies that this isn't a case of the object being modified by reference and wiped out later on? The driver serializes |
The second quote can also hint that whatever happens with the BSON object, also happens with the array and both are wiped out, doesn't it? Maybe the casting from within the driver? As you can see in my previous comment, the problem occurred while executing BTW, we are constantly testing our changes both with php7.0 and php5.6 and php5.6 doesn't seem to produce any errors at all. |
This also happens with MongoDB driver version 1.1.6. Also this is a very serious issue, since it not only happens sometimes that a query is invalid and you get exceptions, but sometimes we also saw that a query was modified somehow somewhere outside of PHP user land code but was still valid and because of this not doing what it is supposed to do, which can be especially bad for update or delete statements. |
@bashofmann, @Shaked: I created a patch for the BulkWrite's debug handler to dump the BSON payload within the This will add a "commands" field to the debug array, in which I'm appending a JSON rendering of each write command's BSON payload (appending JSON strings was much simpler than converting back into a PHP value, and is just as useful in this case). For instance, if the BulkWrite had multiple updates, we might see a single payload for an Would you be able to use this in conjunction with some debugging on the arguments going into the BulkWrite methods to narrow down the point when the data is corrupted? |
This will take a couple of days until we can test this. I'll keep you updated. |
@jmikola Here is another stacktrace with the debug output from your patch
As you can see at this call to MongoDB\Collection::updateOne the query is still correct and both $inc and $set are set.
But the resulting query in the driver sent in the end only has $set set and $inc is empty
|
@Shaked, @bashofmann: Looking at the start of the trace, I see that your update arguments are both PHP arrays:
These later show up as BSONDocument instances, which I assume are generated by these If we look into The error you're seeing looks like a use-after-free scenario, where the array data within the Independent from that, I wonder if constructing the BSONDocument before populating its fields would make a difference. That would mean embedding the logic in In the meantime, I'll also attempt to reproduce this by forcing Also, I didn't see it mentioned above, but do you have any other notable extensions running in PHP 7 when this issue presents itself (e.g. Xdebug)? |
We had the same problem when patching the fromLegacy logic to use a plain array instead of a BSONDocument (see #293 (comment)). The issue only appears infrequently under production load, so I can't really run valgrind. Xdebug is not present. List of extensions:
|
@jmikola Any news on this? I don't know if this is related but there has been an issue in apcu discovered that looks a bit similar: |
@bashofmann: I haven't made any progress on diagnosing this. I've run the extension's BSON tests (90 files) through Valgrind and found nothing that hints towards an issue with the BSON encoding. I assume by this point you've examined the BulkWrite methods and noted how simple they are (calling Is the ticket you referenced indicative of a bug in PHP 7.0 core or just the APCu extension? |
It was a bug in the APCu extension. We tested again with the updated and fixed APCu extension and the issue does not appear anymore so it seems APCu was the culprit, though it is still a bit strange since the BsonDocuments were never stored or read from APCu. Nonetheless, I think we can close the issue :) |
That's good to hear! Would you have a link to the APCu bug/changelog so we can add that here for reference purposes? |
Yes, the one I posted above: |
Thanks @bashofmann! |
Digging this old issue. I'm on PHP 7 and I'm facing the same issue. Not sure what to do. :/ |
@Xonshiz: Please open a new issue. You can always link back to this thread for context. When doing so, the template should request much more information about your environment, so please provide as much of that as possible ("PHP 7" is not nearly enough to go on). Since the issue in this thread was attributed to APCu, it'd be helpful to include any details about that extension in your report. Also, if the error is reproducible, any steps to do so would certainly help. |
Sure, thanks. |
Hey,
We recently switched our production server to PHP7:
And using the new Mongodb driver (1.1.5).
We noticed that sometimes there's a weird behaviour but unfortunately I can't reproduce it yet (it's quite random but for sure happens only on PHP7 servers). When I run the code on dev it works perfectly. I am seeing the following error:
As you can see, the
$set
parameter is definitely not empty. I have tried to debug a bit but still can't figure this issue.I am not sure if this bug should be here so I opened it also under mongo-php-adapter's repository: alcaeus/mongo-php-adapter#93
The moment I have a way to reproduce it, will attach a code snippet but maybe in the meanwhile there's something I have missed.
Thank you
The text was updated successfully, but these errors were encountered: