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

Continually changing behavior of applyOps with an "invalid" update

    • Type: Icon: Bug Bug
    • Resolution: Duplicate
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None
    • Replication
    • ALL
    • Hide
      // Run applyOps in non-atomic mode.
      // For example: applyOps([{op: "i", ns:"test.test", o:{_id:1}}])
      function applyOps(ops, extra) {
      	// Force non-atomic applyOps mode for this batch
      	ops.push({op: "c", ns: "admin.$cmd", o: {applyOps: [{op: "n", ns: "", o: {"msg": "noop"}}]}});
      	var command = {
      		applyOps: ops,
      		writeConcern: {w: "majority"}
      	};
      	var res = db.adminCommand(command);
      	// Avoid noise in output.
      	delete res["operationTime"];
      	delete res["$clusterTime"];
      	return res
      }
      
      db.test.drop()
      db.test.insert({_id:1, a: null});
      
      // Test behavior of an invalid update.
      print('doc before: ' + tojson(db.test.findOne({_id: 1})));
      var res = applyOps([{ns:"test.test", op:"u", o2:{_id:1}, o:{$set:{'a.0':2}}}]);
      print('applyOps result: ' + tojson(res))
      
      print('doc after : ' + tojson(db.test.findOne({_id: 1})));
      
      Show
      // Run applyOps in non-atomic mode. // For example: applyOps([{op: "i" , ns: "test.test" , o:{_id:1}}]) function applyOps(ops, extra) { // Force non-atomic applyOps mode for this batch ops.push({op: "c" , ns: "admin.$cmd" , o: {applyOps: [{op: "n" , ns: "", o: {" msg ": " noop"}}]}}); var command = { applyOps: ops, writeConcern: {w: "majority" } }; var res = db.adminCommand(command); // Avoid noise in output. delete res[ "operationTime" ]; delete res[ "$clusterTime" ]; return res } db.test.drop() db.test.insert({_id:1, a: null }); // Test behavior of an invalid update. print( 'doc before: ' + tojson(db.test.findOne({_id: 1}))); var res = applyOps([{ns: "test.test" , op: "u" , o2:{_id:1}, o:{$set:{ 'a.0' :2}}}]); print( 'applyOps result: ' + tojson(res)) print( 'doc after : ' + tojson(db.test.findOne({_id: 1})));

      I want to bring to light the continually changing behavior of applyOps with an "invalid" update. This is probably working as designed but I want to confirm that the changes are intentional.

      The "invalid" update is attempting to set an array element on a field that is set to null (not an array). See the attached applyOps.js for the repro.

      On 3.2 the server reports success and applies the update:

      $ mongo applyOps.js
      MongoDB shell version v4.0.1
      connecting to: mongodb://127.0.0.1:27017
      MongoDB server version: 3.2.18
      WARNING: shell and server versions do not match
      doc before: { "_id" : 1, "a" : null }
      applyOps result: { "applied" : 2, "results" : [ true, true ], "ok" : 1 }
      doc after : { "_id" : 1, "a" : { "0" : 2 } }
      

      On 3.4 the server reports an error and does not apply the update:

      $ mongo applyOps.js
      MongoDB shell version v4.0.1
      connecting to: mongodb://127.0.0.1:27017
      MongoDB server version: 3.4.18
      WARNING: shell and server versions do not match
      doc before: { "_id" : 1, "a" : null }
      applyOps result: {
      	"applied" : 1,
      	"code" : 16837,
      	"codeName" : "Location16837",
      	"errmsg" : "cannot use the part (a of a.0) to traverse the element ({a: null})",
      	"results" : [
      		false
      	],
      	"ok" : 0
      }
      doc after : { "_id" : 1, "a" : null }
      

      On 3.6, the server reverts back to the 3.2 behavior, reports success and applies the update:

      $ mongo applyOps.js
      MongoDB shell version v4.0.1
      connecting to: mongodb://127.0.0.1:27017
      MongoDB server version: 3.6.9
      WARNING: shell and server versions do not match
      doc before: { "_id" : 1, "a" : null }
      applyOps result: { "applied" : 2, "results" : [ true, true ], "ok" : 1 }
      doc after : { "_id" : 1, "a" : { "0" : 2 } }
      

      Finally on 4.0, the server reports success and does not apply the update:

      $ mongo applyOps.js
      MongoDB shell version v4.0.1
      connecting to: mongodb://127.0.0.1:27017
      MongoDB server version: 4.0.4
      doc before: { "_id" : 1, "a" : null }
      applyOps result: { "applied" : 2, "results" : [ true, true ], "ok" : 1 }
      doc after : { "_id" : 1, "a" : null }
      

            Assignee:
            backlog-server-repl [DO NOT USE] Backlog - Replication Team
            Reporter:
            shane.harvey@mongodb.com Shane Harvey
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Resolved: