mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Selector must be a valid JavaScript object
Error message
Selector must be a valid JavaScript object
What it means
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.
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.
Example fix
// before
collection.updateOne(null, { $set: { a: 1 } });
// after
collection.updateOne({}, { $set: { a: 1 } }); Defensive patterns
Strategy: validation
Validate before calling
function assertFilter(filter) {
if (filter == null || typeof filter !== 'object' || Array.isArray(filter)) {
throw new TypeError('filter must be a plain object');
}
}
assertFilter(myFilter);
collection.updateOne(myFilter, { $set: { x: 1 } }); Type guard
function isFilterObject(v): v is Record<string, unknown> {
return v != null && typeof v === 'object' && !Array.isArray(v);
} Try / catch
try {
await collection.updateOne(filter, update);
} catch (e) {
if (e instanceof MongoInvalidArgumentError && /Selector/.test(e.message)) {
// log and surface a user-facing validation error
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Document must be a valid JavaScript object
- Update operations require that all atomic operators have…
- Argument "update" must be an object
- Invalid read preference mode
- Invalid read preference
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/17720124aff6b438.
Report an issue: GitHub.
Appendix: source
Thrown at src/operations/update.ts:266
return {
acknowledged: this.writeConcern?.w !== 0,
modifiedCount: res.nModified ?? res.n,
upsertedId:
Array.isArray(res.upserted) && res.upserted.length > 0 ? res.upserted[0]._id : null,
upsertedCount: Array.isArray(res.upserted) && res.upserted.length ? res.upserted.length : 0,
matchedCount: Array.isArray(res.upserted) && res.upserted.length > 0 ? 0 : res.n
};
}
}
export function makeUpdateStatement(
filter: Document,
update: Document | Document[],
options: UpdateOptions & { multi?: boolean } & { sort?: Sort }
): UpdateStatement {
if (filter == null || typeof filter !== 'object') {
throw new MongoInvalidArgumentError('Selector must be a valid JavaScript object');
}
if (update == null || typeof update !== 'object') {
throw new MongoInvalidArgumentError('Document must be a valid JavaScript object');
}
const op: UpdateStatement = { q: filter, u: update };
if (typeof options.upsert === 'boolean') {
op.upsert = options.upsert;
}
if (options.multi) {
op.multi = options.multi;
}
if (options.hint) {
op.hint = options.hint;
}View on GitHub (pinned to dce7939f86)