The "unknown operator: $invalidOperator" error in MongoDB occurs when using an unsupported or misspelled query operator in your MongoDB queries. This typically happens due to typos in operator names, using operators from different MongoDB versions, or incorrect operator syntax. The error indicates that MongoDB does not recognize the operator you're trying to use in your query.
The "unknown operator: $invalidOperator" error in MongoDB is a query validation error that occurs when you use an operator that MongoDB does not recognize or support. MongoDB has a specific set of query operators that can be used in find(), update(), aggregate(), and other operations, each with a specific syntax and purpose. When you construct a MongoDB query, you use operators like $eq, $gt, $in, $regex, etc., to specify conditions and operations. If you use an operator that doesn't exist (due to a typo), isn't supported in your MongoDB version, or isn't valid for the operation you're performing, MongoDB will reject the query with this error. Common scenarios where this error appears: - **Typographical errors**: Misspelling operator names like "$gte" as "$get" or "$in" as "$inn" - **Version mismatches**: Using operators introduced in newer MongoDB versions with an older server - **Context errors**: Using aggregation operators in find queries or vice versa - **Case sensitivity**: MongoDB operators are case-sensitive - "$regex" works but "$Regex" doesn't - **Invalid combinations**: Trying to use operators in contexts where they're not allowed - **Driver vs server mismatch**: Using operators supported by the driver but not by the server version The error is particularly common when: 1. Migrating code between MongoDB versions 2. Copy-pasting queries from documentation or examples 3. Working with complex aggregation pipelines 4. Using third-party libraries that generate MongoDB queries
First, check the exact spelling of the operator causing the error. MongoDB operators are case-sensitive and must be spelled exactly as documented.
Common operator spelling mistakes:
- "$gte" (greater than or equal) vs "$get" (invalid)
- "$lte" (less than or equal) vs "$let" (invalid)
- "$in" (in array) vs "$inn" (invalid)
- "$regex" (regular expression) vs "$Regex" or "$REGEX" (invalid)
- "$exists" (field exists) vs "$exist" (invalid)
Check your query:
// Example of incorrect query
db.collection.find({
age: { $get: 18 } // ERROR: Should be $gte
});
// Correct query
db.collection.find({
age: { $gte: 18 } // CORRECT
});
// Another common mistake
db.collection.find({
tags: { $inn: ['mongodb', 'nodejs'] } // ERROR: Should be $in
});
// Correct
db.collection.find({
tags: { $in: ['mongodb', 'nodejs'] } // CORRECT
});Use MongoDB documentation to verify operator names:
1. Query and Projection Operators: https://www.mongodb.com/docs/manual/reference/operator/query/
2. Update Operators: https://www.mongodb.com/docs/manual/reference/operator/update/
3. Aggregation Pipeline Operators: https://www.mongodb.com/docs/manual/reference/operator/aggregation/
Quick reference of common operators:
- Comparison: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin
- Logical: $and, $or, $not, $nor
- Element: $exists, $type
- Evaluation: $expr, $jsonSchema, $mod, $regex, $text, $where
- Array: $all, $elemMatch, $size
- Update: $set, $unset, $inc, $min, $max, $mul, $rename, $currentDate
Verify that the operator you're using is supported in your MongoDB server version. Some operators were introduced in specific MongoDB versions.
Check your MongoDB server version:
# In mongosh or mongo shell
db.version()
# Or from command line
mongod --versionCommon version-specific operators:
- MongoDB 5.0+: $getField, $setField, $unsetField, $replaceWith (in updates)
- MongoDB 4.4+: $unionWith (aggregation), $convert, $toBool, $toString, etc.
- MongoDB 4.2+: $merge (aggregation), $replaceRoot with new syntax
- MongoDB 4.0+: $convert, $toObjectId, $dateFromString (type conversion operators)
If using a newer operator with an older MongoDB server:
// MongoDB 5.0+ operator (won't work in 4.x)
db.collection.updateOne(
{ _id: 1 },
{ $setField: { field: "status", value: "active" } } // ERROR in MongoDB 4.x
);
// Alternative for older versions
db.collection.updateOne(
{ _id: 1 },
{ $set: { status: "active" } } // Works in all versions
);Check operator documentation for version requirements:
# Example: Check if $unionWith is available
# Requires MongoDB 4.4+
# If running MongoDB 4.2, this will fail
db.collection.aggregate([
{ $unionWith: "otherCollection" } // ERROR in MongoDB < 4.4
]);Solution options:
1. Upgrade MongoDB server to required version
2. Use alternative operators that work in your version
3. Rewrite query logic without the unsupported operator
4. Use application-level logic instead of database operator
Ensure the operator is being used in the correct context. Some operators are only valid for specific operations.
Common context errors:
1. Using aggregation operators in find queries:
// ERROR: $match is an aggregation operator, not a query operator
db.collection.find({ $match: { status: "active" } });
// CORRECT: Use standard query operators
db.collection.find({ status: "active" });
// CORRECT: $match in aggregation pipeline
db.collection.aggregate([{ $match: { status: "active" } }]);2. Using query operators in update operations:
// ERROR: $gt is a query operator, not an update operator
db.collection.updateOne({}, { $gt: { count: 5 } });
// CORRECT: Use update operators
db.collection.updateOne({}, { $inc: { count: 1 } });
// CORRECT: $gt in query filter, update operators in update
db.collection.updateOne(
{ count: { $gt: 5 } }, // Query filter
{ $set: { status: "high" } } // Update operation
);3. Operator in wrong position:
// ERROR: $and at wrong level
db.collection.find({
$and: { status: "active", age: { $gt: 18 } } // Should be array
});
// CORRECT: $and expects array of conditions
db.collection.find({
$and: [
{ status: "active" },
{ age: { $gt: 18 } }
]
});
// Even better: implicit $and
db.collection.find({
status: "active",
age: { $gt: 18 }
});4. Invalid operator for field type:
// ERROR: $size on non-array field
db.collection.find({ name: { $size: 5 } });
// CORRECT: $size only works on arrays
db.collection.find({ tags: { $size: 5 } });
// CORRECT: For strings, use $strLenBytes or $strLenCP (aggregation)
// or application-level string length checkCheck operator documentation for valid contexts:
- Query operators: Used in find(), findOne(), count(), etc. filters
- Update operators: Used in updateOne(), updateMany(), findOneAndUpdate()
- Aggregation operators: Used in aggregate() pipeline stages
- Projection operators: Used in find() projection parameter
Use debugging techniques to identify the exact issue with your query.
1. Enable MongoDB query logging:
# Start mongod with verbose logging
mongod --verbose
# Or enable profiling
db.setProfilingLevel(2) // Log all queries
# Check the profiler for failed queries
db.system.profile.find({ err: { $exists: true } }).pretty()2. Validate queries before execution (Node.js driver):
const { MongoClient } = require('mongodb');
async function validateQuery(collection, query) {
try {
// Try to explain the query (validates without executing)
await collection.find(query).explain();
console.log('Query is valid');
return true;
} catch (error) {
console.log('Query validation failed:', error.message);
// Check if it's an unknown operator error
if (error.message.includes('unknown operator')) {
// Extract operator name from error message
const match = error.message.match(/\$(\w+)/);
if (match) {
console.log('Invalid operator detected: $' + match[1]);
}
}
return false;
}
}
// Usage
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const db = client.db('test');
const collection = db.collection('users');
const invalidQuery = { age: { $get: 18 } }; // Invalid operator
await validateQuery(collection, invalidQuery);3. Use MongoDB Compass to validate queries:
- Open MongoDB Compass
- Connect to your database
- Use the query bar to test queries
- Compass will highlight syntax errors and suggest corrections
4. Create a query validator function:
const validOperators = new Set([
// Comparison operators
'eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin',
// Logical operators
'and', 'or', 'not', 'nor',
// Element operators
'exists', 'type',
// Evaluation operators
'expr', 'jsonSchema', 'mod', 'regex', 'text', 'where',
// Array operators
'all', 'elemMatch', 'size'
]);
function validateQueryOperators(query, path = '') {
for (const [key, value] of Object.entries(query)) {
if (key.startsWith('$')) {
const operator = key.substring(1);
if (!validOperators.has(operator)) {
throw new Error('Invalid operator $' + operator + ' at path: ' + path);
}
}
if (value && typeof value === 'object' && !Array.isArray(value)) {
validateQueryOperators(value, path ? path + '.' + key : key);
}
}
}
// Usage
try {
validateQueryOperators({ age: { $get: 18 } });
} catch (error) {
console.log('Validation error:', error.message);
}Here are common operator mistakes and their correct alternatives:
1. $get vs $gte:
// WRONG
db.collection.find({ age: { $get: 18 } });
// CORRECT
db.collection.find({ age: { $gte: 18 } });2. $contains vs $in (for array membership):
// WRONG (common misconception)
db.collection.find({ tags: { $contains: 'mongodb' } });
// CORRECT: Check if array contains value
db.collection.find({ tags: 'mongodb' }); // Shorthand
// CORRECT: Check if value is in array
db.collection.find({ role: { $in: ['admin', 'editor'] } });3. $like vs $regex (for pattern matching):
// WRONG (SQL habit)
db.collection.find({ name: { $like: '%john%' } });
// CORRECT: Use $regex
db.collection.find({ name: { $regex: 'john', $options: 'i' } });
// CORRECT: Case-insensitive search
db.collection.find({ name: { $regex: '^john', $options: 'i' } });4. $between vs $gte + $lte:
// WRONG (SQL habit)
db.collection.find({ age: { $between: [18, 65] } });
// CORRECT: Use $gte and $lte
db.collection.find({
age: { $gte: 18, $lte: 65 }
});
// OR use $and for clarity
db.collection.find({
$and: [
{ age: { $gte: 18 } },
{ age: { $lte: 65 } }
]
});5. String length checks:
// WRONG: $length doesn't exist
db.collection.find({ name: { $length: 5 } });
// CORRECT: Use aggregation for string length
db.collection.aggregate([
{ $match: { $expr: { $eq: [{ $strLenCP: "$name" }, 5] } } }
]);
// CORRECT: Application-level filtering
// Fetch then filter in application code6. Null/empty checks:
// WRONG: $empty doesn't exist
db.collection.find({ comments: { $empty: true } });
// CORRECT: Check for null/empty array
db.collection.find({
$or: [
{ comments: null },
{ comments: { $size: 0 } }
]
});
// CORRECT: $exists check
db.collection.find({ comments: { $exists: false } });Remember: When in doubt, consult the official MongoDB documentation for the complete list of valid operators for your MongoDB version.
Implement practices to prevent unknown operator errors in the future:
1. Use TypeScript with MongoDB driver types:
import { MongoClient, Filter, UpdateFilter } from 'mongodb';
// Type-safe query construction
const query: Filter<Document> = {
age: { $gte: 18 }, // TypeScript will catch $get typo
status: { $in: ['active', 'pending'] }
};
const update: UpdateFilter<Document> = {
$set: { lastLogin: new Date() },
$inc: { loginCount: 1 }
};
// TypeScript error for invalid operator
const invalidQuery = {
age: { $get: 18 } // TypeScript error: $get not assignable
};2. Create operator constants or utilities:
// operator-utils.js
const Operators = {
COMPARISON: {
EQ: '$eq',
NE: '$ne',
GT: '$gt',
GTE: '$gte',
LT: '$lt',
LTE: '$lte',
IN: '$in',
NIN: '$nin'
},
LOGICAL: {
AND: '$and',
OR: '$or',
NOT: '$not',
NOR: '$nor'
}
// ... other operator categories
};
// Usage
const query = {
age: { [Operators.COMPARISON.GTE]: 18 },
status: { [Operators.COMPARISON.IN]: ['active', 'pending'] }
};
// This prevents typos3. Implement query validation middleware:
// query-validator.js
const validOperators = require('./valid-operators.json');
function validateMongoQuery(query, context = 'find') {
const errors = [];
function traverse(obj, path = '') {
for (const [key, value] of Object.entries(obj)) {
if (key.startsWith('$')) {
const operator = key.substring(1);
if (!validOperators[context].includes(operator)) {
errors.push('Invalid ' + context + ' operator $' + operator + ' at ' + path);
}
}
if (value && typeof value === 'object') {
traverse(value, path ? path + '.' + key : key);
}
}
}
traverse(query);
return errors;
}
// Usage in application
const query = { age: { $get: 18 } };
const errors = validateMongoQuery(query, 'find');
if (errors.length > 0) {
console.log('Query validation errors:', errors);
throw new Error('Invalid query');
}4. Version-aware query building:
// version-aware-queries.js
const MONGODB_VERSION = process.env.MONGODB_VERSION || '5.0';
const versionConstraints = {
'5.0': ['$getField', '$setField', '$unsetField'],
'4.4': ['$unionWith', '$convert', '$toBool'],
'4.2': ['$merge'],
'4.0': ['$convert', '$toObjectId']
};
function isOperatorSupported(operator) {
const version = MONGODB_VERSION;
for (const [minVersion, operators] of Object.entries(versionConstraints)) {
if (compareVersions(version, minVersion) >= 0) {
if (operators.includes(operator)) {
return true;
}
}
}
return false; // Assume supported if not in constraints
}
function buildSafeQuery(baseQuery) {
const safeQuery = { ...baseQuery };
// Remove unsupported operators
// ... implementation
return safeQuery;
}5. Regular MongoDB version audits:
- Document MongoDB version in use
- Track operator usage in codebase
- Test queries against target MongoDB version in CI/CD
- Update documentation when upgrading MongoDB
6. Use MongoDB Compass for query development:
- Develop and test queries in MongoDB Compass first
- Use query history to track changes
- Export valid queries to application code
Understanding MongoDB Operator Architecture:
MongoDB operators are implemented as part of the query engine and are version-specific. When you submit a query:
1. Query Parsing: MongoDB parses the query JSON and validates operator names
2. Operator Resolution: Each operator is mapped to internal query operations
3. Type Checking: Operators are validated against field types and contexts
4. Execution Plan: Valid operators are compiled into an execution plan
Common Operator Categories:
1. Query Operators: Used in find(), count(), delete operations
- Comparison: Work with field values ($eq, $gt, etc.)
- Logical: Combine multiple conditions ($and, $or, etc.)
- Element: Check field existence/type ($exists, $type)
- Evaluation: Perform computations in queries ($regex, $text, etc.)
- Array: Work with array fields ($all, $elemMatch, $size)
2. Update Operators: Used in update operations
- Field Update: $set, $unset, $rename, $inc, $mul, $min, $max
- Array Update: $push, $pull, $pop, $addToSet, $pullAll
- Bitwise: $bit (and, or, xor)
- Current Date: $currentDate
3. Aggregation Operators: Used in aggregation pipelines
- Stage Operators: $match, $group, $project, $sort, etc.
- Expression Operators: Mathematical, string, array, date operations
- Variable Operators: $$ROOT, $$CURRENT, etc.
Operator Name Conventions:
- All operators start with "$"
- Names are lowercase (case-sensitive)
- Names are usually abbreviated ($eq not $equals, $gt not $greaterThan)
- Logical operators often match programming language keywords ($and, $or, $not)
Debugging Unknown Operator Errors:
1. Enable MongoDB logging:
# Start mongod with detailed logging
mongod --logpath /var/log/mongodb/mongod.log --logappend --verbose
# Check logs for query parsing errors
tail -f /var/log/mongodb/mongod.log | grep "unknown operator"2. Use explain() to see query parsing:
try {
db.collection.find({ age: { $get: 18 } }).explain();
} catch (e) {
console.log('Error during explain:', e.message);
}3. Check driver compatibility matrix:
- MongoDB Node.js driver compatibility: https://www.mongodb.com/docs/drivers/node/current/compatibility/
- Other drivers have similar compatibility tables
Migration Considerations:
When upgrading MongoDB versions:
1. Test all queries with new version in staging
2. Identify operators that may be deprecated or changed
3. Update application code before production deployment
4. Consider using feature compatibility version (FCV) for gradual upgrades
For MongoDB Atlas users:
- Atlas automatically manages MongoDB versions
- Check Atlas release notes for operator changes
- Use Atlas UI to test queries before updating application code
- Consider using version tags in connection strings for compatibility
StaleShardVersion: shard version mismatch
How to fix "StaleShardVersion: shard version mismatch" in MongoDB
MongoOperationTimeoutError: Operation timed out
How to fix "MongoOperationTimeoutError: Operation timed out" in MongoDB
MongoServerError: PlanExecutor error during aggregation :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation.
How to fix "QueryExceededMemoryLimitNoDiskUseAllowed" in MongoDB
MissingSchemaError: Schema hasn't been registered for model
How to fix "MissingSchemaError: Schema hasn't been registered for model" in MongoDB/Mongoose
DivergentArrayError: For your own good, using document.save() to update an array which was selected using an $elemMatch projection will not work
How to fix "DivergentArrayError: For your own good, using document.save() to update an array which was selected using an $elemMatch projection will not work" in MongoDB