{"record":{"id":"17720124aff6b438","repo":"mongodb/node-mongodb-native","slug":"selector-must-be-a-valid-javascript-object","errorCode":null,"errorMessage":"Selector must be a valid JavaScript object","messagePattern":"Selector must be a valid JavaScript object","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/operations/update.ts","lineNumber":266,"sourceCode":"\n    return {\n      acknowledged: this.writeConcern?.w !== 0,\n      modifiedCount: res.nModified ?? res.n,\n      upsertedId:\n        Array.isArray(res.upserted) && res.upserted.length > 0 ? res.upserted[0]._id : null,\n      upsertedCount: Array.isArray(res.upserted) && res.upserted.length ? res.upserted.length : 0,\n      matchedCount: Array.isArray(res.upserted) && res.upserted.length > 0 ? 0 : res.n\n    };\n  }\n}\n\nexport function makeUpdateStatement(\n  filter: Document,\n  update: Document | Document[],\n  options: UpdateOptions & { multi?: boolean } & { sort?: Sort }\n): UpdateStatement {\n  if (filter == null || typeof filter !== 'object') {\n    throw new MongoInvalidArgumentError('Selector must be a valid JavaScript object');\n  }\n\n  if (update == null || typeof update !== 'object') {\n    throw new MongoInvalidArgumentError('Document must be a valid JavaScript object');\n  }\n\n  const op: UpdateStatement = { q: filter, u: update };\n  if (typeof options.upsert === 'boolean') {\n    op.upsert = options.upsert;\n  }\n\n  if (options.multi) {\n    op.multi = options.multi;\n  }\n\n  if (options.hint) {\n    op.hint = options.hint;\n  }","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/update.ts#L248-L284","documentation":"Thrown by makeUpdateStatement() (src/operations/update.ts:266) when the filter argument to an update operation is null or not a plain object. The driver validates the filter (the 'q' field of the wire-protocol update statement) before constructing the op, since the server cannot match documents against a non-object selector. This surfaces as a MongoInvalidArgumentError synchronously from collection.updateOne/updateMany/findOneAndUpdate/bulkWrite when the filter is malformed.","triggerScenarios":"Calling collection.updateOne(null, {...}), collection.updateOne(undefined, {...}), collection.replaceOne(42, {...}), or passing a filter that is an array/primitive. Also triggered by bulkWrite when an UpdateOne/ReplaceOne statement carries a non-object filter.","commonSituations":"Constructing a filter from user input that was not provided (undefined), deserializing JSON where the filter key is missing, or accidentally passing the update document as the first argument.","solutions":["Ensure the first argument to updateOne/updateMany/replaceOne/findOneAndUpdate is a non-null object (e.g. {} to match all).","If the filter may be absent, default it: collection.updateOne(filter ?? {}, update).","Add a runtime guard that rejects non-object filters before calling the driver API."],"exampleFix":"// before\ncollection.updateOne(null, { $set: { a: 1 } });\n// after\ncollection.updateOne({}, { $set: { a: 1 } });","handlingStrategy":"validation","validationCode":"function assertFilter(filter) {\n  if (filter == null || typeof filter !== 'object' || Array.isArray(filter)) {\n    throw new TypeError('filter must be a plain object');\n  }\n}\nassertFilter(myFilter);\ncollection.updateOne(myFilter, { $set: { x: 1 } });","typeGuard":"function isFilterObject(v): v is Record<string, unknown> {\n  return v != null && typeof v === 'object' && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  await collection.updateOne(filter, update);\n} catch (e) {\n  if (e instanceof MongoInvalidArgumentError && /Selector/.test(e.message)) {\n    // log and surface a user-facing validation error\n  }\n  throw e;\n}","preventionTips":["Type the filter parameter as Document (not any) so the compiler rejects non-objects.","Default missing filters to {} at API boundaries.","Validate user input that becomes a filter before passing it to the driver."],"tags":["validation","update","crud","invalid-argument"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}