mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Query filter must be a plain object or ObjectId
Error message
Query filter must be a plain object or ObjectId
What it means
The FindOperation constructor (src/operations/find.ts:101) validates that the `filter` argument is a plain object (typeof 'object' and not an array). If a non-object or an array is passed, a MongoInvalidArgumentError is thrown before any server interaction. This is a client-side guard; the special case of passing an ObjectId is handled separately (it is wrapped into { _id: filter }).
Source
Thrown at src/operations/find.ts:101
/**
* @remarks WriteConcern can still be present on the options because
* we inherit options from the client/db/collection. The
* key must be present on the options in order to delete it.
* This allows typescript to delete the key but will
* not allow a writeConcern to be assigned as a property on options.
*/
override options: FindOptions & { writeConcern?: never };
filter: Document;
constructor(ns: MongoDBNamespace, filter: Document = {}, options: FindOptions = {}) {
super(undefined, options);
this.options = { ...options };
delete this.options.writeConcern;
this.ns = ns;
if (typeof filter !== 'object' || Array.isArray(filter)) {
throw new MongoInvalidArgumentError('Query filter must be a plain object or ObjectId');
}
// special case passing in an ObjectId as a filter
this.filter = filter != null && filter._bsontype === 'ObjectId' ? { _id: filter } : filter;
this.SERVER_COMMAND_RESPONSE_TYPE = this.explain ? ExplainedCursorResponse : CursorResponse;
}
override get commandName() {
return 'find' as const;
}
override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
return {
...this.options,
...this.bsonOptions,
documentsReturnedIn: 'firstBatch',
session: this.session,View on GitHub (pinned to 3366c21a63)
Solutions
- Pass a plain object as the filter, e.g. collection.find({ status: 'active' }).
- To query by _id, use collection.find({ _id: new ObjectId(id) }) or pass the ObjectId directly.
- For multiple values, use $in: collection.find({ sku: { $in: ['a','b'] } }).
Example fix
// before
const cursor = collection.find('abc'); // string, not an object
// after
const cursor = collection.find({ name: 'abc' });
// or by id:
const cursor = collection.find({ _id: new ObjectId('abc...') }); Defensive patterns
Strategy: type-guard
Validate before calling
function isPlainObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
}
// usage before find:
if (!isPlainObject(filter)) {
throw new TypeError('filter must be a plain object or ObjectId');
} Type guard
const isPlainObjectFilter = (f: unknown): boolean => (typeof f === 'object' && f !== null && !Array.isArray(f)) || (f != null && (f as any)._bsontype === 'ObjectId');
Prevention
- Always pass a query document object to find(), never a bare value.
- Use { _id: new ObjectId(id) } to query by identifier.
- Enable TypeScript strict checks so non-object filters fail at compile time.
When it happens
Trigger: Calling collection.find('string'), collection.find(42), collection.find([1,2]), or collection.find(null) — any filter that is not a plain object or an ObjectId.
Common situations: Passing a value where a query document is expected — e.g. passing an ID string instead of {_id: id}, or passing an array of values hoping for an $in shorthand.
Related errors
- Argument "filter" must be an object
- Argument "replacement" must be an object
- Replacement document must not contain atomic operators
- Argument "update" must be an object
- Bulk find operation must specify a selector
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/41891d6f0c38ec6a.json.
Report an issue: GitHub.