meteor/meteor · error · MiniMongoQueryError
$or/$and/$nor entries need to be full objects
Error message
$or/$and/$nor entries need to be full objects
What it means
Each element of an $and/$or/$nor array must itself be a full document selector (a plain object), checked with LocalCollection._isPlainObject. This guards the .map in compileArrayOfDocumentSelectors, ensuring each branch is a valid sub-selector rather than a scalar, array, or class instance. MongoDB applies the same rule: every array entry is interpreted as a separate query document.
Source
Thrown at packages/minimongo/common.js:561
delete match.distance;
delete match.arrayIndices;
}
return match;
};
}
const andDocumentMatchers = andSomeMatchers;
const andBranchedMatchers = andSomeMatchers;
function compileArrayOfDocumentSelectors(selectors, matcher, inElemMatch) {
if (!Array.isArray(selectors) || selectors.length === 0) {
throw new MiniMongoQueryError('$and/$or/$nor must be nonempty array');
}
return selectors.map(subSelector => {
if (!LocalCollection._isPlainObject(subSelector)) {
throw new MiniMongoQueryError('$or/$and/$nor entries need to be full objects');
}
return compileDocumentSelector(subSelector, matcher, {inElemMatch});
});
}
// Takes in a selector that could match a full document (eg, the original
// selector). Returns a function mapping document->result object.
//
// matcher is the Matcher object we are compiling.
//
// If this is the root document selector (ie, not wrapped in $and or the like),
// then isRoot is true. (This is used by $near.)
export function compileDocumentSelector(docSelector, matcher, options = {}) {
const docMatchers = Object.keys(docSelector).map(key => {
const subSelector = docSelector[key];
if (key.substr(0, 1) === '$') {View on GitHub (pinned to 5076d2f818)
Solutions
- Wrap each scalar entry as a document: map ids to {_id: id} before $or.
- Validate with selectors.every(s => LocalCollection._isPlainObject(s)) before querying.
- Re-check the shape of any selector coming from JSON.parse or an EJSON payload.
Example fix
// before
db.find({ $or: idList });
// after
db.find({ $or: idList.map(id => ({ _id: id })) }); Defensive patterns
Strategy: validation
Validate before calling
function normalizeOr(items) {
if (!items.every(x => x && typeof x === 'object' && !Array.isArray(x))) {
throw new TypeError('$or entries must be plain objects');
}
return items;
}
db.find({ $or: normalizeOr(rawList) }); Type guard
function isPlainObjectList(arr) {
return Array.isArray(arr) && arr.every(
x => x !== null && Object.getPrototypeOf(x) === Object.prototype);
} Prevention
- Always wrap raw ids as {_id: id} before placing in $or.
- Validate selector shape with a schema (e.g. ajv) in API boundaries.
- Avoid passing class instances (Date, ObjectId wrappers) directly into selector arrays.
When it happens
Trigger: Passing {$or: [1, 2]}, {$or: ['foo']}, {$and: [{a:1}, [1,2]]}, or an array containing a Date / ObjectId / EJSON-serialized value that is not a plain object.
Common situations: Spreading a mixed list into $or where some entries are raw ids instead of {_id: id} objects, or de-serializing a selector whose array elements lost their plain-object prototype.
Related errors
- $and/$or/$nor must be nonempty array
- Unrecognized logical operator: ${key}
- unknown string alias for $type: ${operand}
- Invalid numerical $type code: ${operand}
- argument to $type is not a number or a string
AI-assisted analysis of meteor/meteor@5076d2f818 (2026-08-13).
Data as JSON: /api/errors/8b45cc1812a82314.
Report an issue: GitHub.