Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-98674

IDHack upsert erroneously dup key errors

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 8.1.0-rc0
    • Component/s: None
    • None
    • Query Execution
    • ALL
    • 200

      db.c.insert({_id: 1});
      db.c.update({_id: {$eq: 1}}, {$set: {a: 1}}, {upsert: true});

      This originally manifested as FLE2 crash, here's the writeup detailing that:

      It falls into the insert codepath which inserts a duplicate _id value. At the time of filing, this causes a crash due to an incorrect retry in multidocument transactions. After SERVER-95524, the insert will not retry and instead duplicate key error. The upsert should succeed in this case.

      All FLE2 queries run in multidocument transactions, because their writes to encrypted state collections ESC and ECOC must be written atomically with encrypted user data writes.

      Repro (must run with --suites=fle2, thanks haley.connelly@mongodb.com for providing a version of this).

      /**
       * Reproduces a server crash when a duplicate upsert is run using FLE.
       *
       * resmoke --suites=fle2 failedWuowCrashWithFle.js
       */
      import {EncryptedClient} from "jstests/fle2/libs/encrypted_client_util.js";// sleep(10000);
      let dbName = 'test';
      let collName = 'test';
      let dbTest = db.getSiblingDB(dbName);
      dbTest.dropDatabase();
      let client = new EncryptedClient(db.getMongo(), dbName);
      assert.commandWorked(client.createEncryptionCollection(collName, {
          validator: {$jsonSchema: {required: ["a"]}},
          encryptedFields: {
              "fields": [
                  {"path": "a", "bsonType": "string", "queries": {"queryType": "equality"}},
              ]
          }
      }));let edb = client.getDB();
      const ecoll = client.getDB()[collName];
      assert.commandWorked(ecoll.einsert({_id: 1, "a": "a"}));
      assert(ecoll.ecount({}) === 1);
      jsTest.log(ecoll.efindOne({}));
      assert.commandWorked(ecoll.eupdate({_id: 1}, {$set: {"a": "a"}}, true /*upsert*/, false /*multi*/));
      assert(ecoll.ecount({}) === 1);
      jsTest.log(ecoll.efindOne({}));
      

      Some open background questions:

      • What are the "tags" that FLE2 implementation refers to?

            Assignee:
            evan.bergeron@mongodb.com Evan Bergeron
            Reporter:
            evan.bergeron@mongodb.com Evan Bergeron
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: