Skip to content
MongoDB

MongoDB Error 2

BadValue: unknown operator and other invalid query values

Applies to: MongoDB 7.0 and 8.0 (wordings checked against the 8.0 source)
Last technically reviewed 24 October 2026 on MongoDB 8.0 documentation and source (error_codes.yml r8.0.0); not run locally
The full message
MongoServerError: unknown operator: $equals
Other forms of this message
An unknown operator at the top level of the filter (8.0 adds a hint)
unknown top level operator: $email. If you have a field name that starts with a '$' symbol, consider using $getField or $setField.
$not used at the top level
unknown top level operator: $not. If you are trying to negate an entire expression, use $nor.
$in or $nin given a single value instead of an array
$in needs an array
$and, $or or $nor given the wrong shape (three separate messages)
$or argument must be an array
$or argument must be a non-empty array
$or argument's entries must be objects
hint() names an index that does not exist
hint provided does not correspond to an existing index
$regex given a value that is not a string
$regex has to be a string
Python (PyMongo raises OperationFailure; the reply document is appended)
pymongo.errors.OperationFailure: unknown operator: $equals, full error: {'ok': 0.0, 'errmsg': 'unknown operator: $equals', 'code': 2, 'codeName': 'BadValue'}
Error code
2
Code name
BadValue
Product
MongoDB
Versions
MongoDB 7.0 and 8.0 (wordings checked against the 8.0 source)
Last reviewed
24 October 2026

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))
What to look for

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 }))
What to look for

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 } })
What to look for

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 side

Replace 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 side

Wrap 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 side

Use 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 side

When 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 } })
Expected result (documented format, not run)
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" } })
Expected result (documented format, not run)
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 } } })
Expected result (documented format, not run)
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.

Still stuck on a MongoDB error?

Browse the full MongoDB error library, or get hands-on help from an experienced SQL professional.