- Error code
- 2
- Code name
BadValue- Product
- MongoDB
- Versions
- MongoDB 7.0 and 8.0 (wordings checked against the 8.0 source)
- Category
- Queries & Aggregation
- Last reviewed
- 24 October 2026
On this page
What it means
Error 2 (BadValue) is MongoDB's generic "this value is not acceptable" code. In queries it most often means a misspelt or misplaced operator, a single value where an array is required, or a hint that names no existing index.
BadValue is not one error but a family. The code says only that a value in the request was rejected; the message says which one, so read the text after MongoServerError: and do not match on the code alone. The wordings below are the common query forms in MongoDB 8.0's query parser; other commands (configuration, administration) use code 2 with their own texts, so this list is not exhaustive.
unknown operator means a name starting with $ inside a field condition is not a query operator, as in { price: { $equals: 10 } } (the operator is $eq). unknown top level operator means the same at the root of the filter: only operators such as $and, $or, $nor, $expr and $text may appear there. In 8.0 the message adds a hint: for $not it suggests $nor, because $not only works on a field condition; for anything else it points to $getField, because a field name that really starts with $ cannot be queried directly.
needs an array and argument must be an array mean $in, $nin, $all, $and, $or or $nor received a single value or object. hint provided does not correspond to an existing index comes from the query planner when no index on the collection matches the name or key pattern passed to hint(). For parse errors in aggregation stage options, MongoDB more often uses 9 FailedToParse.
Common causes
- A misspelt or invented operator, such as $equals, $contains or $notEqual, instead of $eq, $regex or $ne.
- An operator placed at the wrong level: $not wrapping a whole filter, or a field condition such as $gt written at the top level.
- A filter built from user input or a JSON body whose keys start with $, which MongoDB then reads as operators.
- A single value passed to $in or $nin, or an object passed to $or, often because application code did not wrap a value in an array.
- A hint naming an index that was renamed, dropped or never created on this collection (or on this environment).
Diagnose it
Read-only These mongosh commands only read data, indexes, statistics and server state (find, aggregate without $out or $merge, getIndexes, stats, currentOp, rs.status). They do not change data, users or settings, so they are safe to run first.
Print the filter your code actually sends
// in mongosh, or log the same object in your application
const filter = { price: { $equals: 10 } }
print(EJSON.stringify(filter)) The exact filter document. Compare every key that starts with $ with the query operator list, and check that $in, $nin, $and and $or receive arrays.
List index names before using hint()
db.products.getIndexes().map(ix => ({ name: ix.name, key: ix.key })) Each index name and key pattern. The value passed to hint() must match one of them exactly, by name (such as category_1_price_-1) or by key pattern.
Test the corrected condition on its own
db.products.countDocuments({ price: { $eq: 10 } }) A count instead of an error. Rebuild the full filter one condition at a time until the failing part is found.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Use the correct operator at the correct level
Client or network sideReplace the unknown name with the real operator, and put field operators inside the field. To negate a whole condition use $nor, or put $not inside the field.
// field condition
db.products.find({ price: { $eq: 10 } })
// negate a whole condition
db.products.find({ $nor: [ { price: { $gt: 100 } } ] })
db.products.find({ price: { $not: { $gt: 100 } } })
Pass arrays to $in, $nin and the logical operators
Client or network sideWrap single values in an array in application code, and give $or an array of condition objects.
db.products.find({ category: { $in: [ "books" ] } })
db.products.find({ $or: [ { category: "books" }, { price: { $lt: 5 } } ] })
Hint an index that exists, or remove the hint
Client or network sideUse a name or key pattern from getIndexes(). A hint is optional: without it the planner chooses an index itself, so remove hints that point at indexes some environments do not have.
db.products.find({ category: "books" }).hint({ category: 1, price: -1 })
Reject keys that start with $ in user input
Client or network sideWhen filters are built from request data, accept only the field names you expect and refuse any key starting with $. This prevents both this error and operator injection.
Examples
A misspelt comparison operator
Not reproduced here: no MongoDB server is installed for this site. The text is the one built by parseSubField() in MongoDB 8.0's expression_parser.cpp, shown as mongosh prints a server error; the collection and operator name are this example's.
db.products.find({ price: { $equals: 10 } })
MongoServerError: unknown operator: $equals
A single value given to $in
Not reproduced here: no MongoDB server is installed for this site. The text is the fixed string returned by MongoDB 8.0's query parser (expression_parser.cpp) when $in receives a value that is not an array.
db.products.find({ category: { $in: "books" } })
MongoServerError: $in needs an array
$not wrapped around the whole filter
Not reproduced here: no MongoDB server is installed for this site. The text, including the hint about $nor, is built in MongoDB 8.0's expression_parser.cpp (the hint is not present in older versions); the filter is illustrative.
db.products.find({ $not: { price: { $gt: 100 } } })
MongoServerError: unknown top level operator: $not. If you are trying to negate an entire expression, use $nor.
How to prevent it
Build filters with your driver's types or a query builder rather than string concatenation, and keep a short unit test for each query shape so a misspelt operator fails in CI, not in production.
Whitelist field names from user input, normalise single values into arrays before using $in, and avoid hard-coded hints unless every environment has the same indexes.
Common questions
What does "unknown operator" mean in MongoDB?
A key starting with $ inside a field condition is not a query operator MongoDB knows, usually a typo such as $equals for $eq or $contains instead of $regex. Correct the name using the query operator list.
What is the difference between "unknown operator" and "unknown top level operator"?
The first is inside a field, as in { price: { $foo: 1 } }. The second is at the root of the filter, as in { $foo: 1 } or { $not: {...} }; only operators such as $and, $or, $nor and $expr may appear there.
Why does MongoDB say "hint provided does not correspond to an existing index"?
No index on the collection matches the name or key pattern passed to hint(). Check getIndexes() on that collection and environment, then fix or remove the hint.
Learn more on CodeWithSQL
Official documentation
Last technically reviewed 24 October 2026; examples and diagnostics run on MongoDB 8.0 documentation and source (error_codes.yml r8.0.0); not run locally. Codes and code names are checked against MongoDB's error_codes.yml (8.0); no MongoDB server was available, so the examples were not run locally.