{"record":{"id":"aa6f008dc8dec2fe","repo":"Automattic/mongoose","slug":"can-t-use-conditional","errorCode":null,"errorMessage":"Can't use ${conditional}","messagePattern":"Can't use (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/schema/subdocument.js","lineNumber":240,"sourceCode":"  }\n\n  return subdoc;\n};\n\n/**\n * Casts contents for query\n *\n * @param {string} [$conditional] optional query operator (like `$eq` or `$in`)\n * @param {any} value\n * @api private\n */\n\nSchemaSubdocument.prototype.castForQuery = function($conditional, val, context, options) {\n  let handler;\n  if ($conditional != null) {\n    handler = this.$conditionalHandlers[$conditional];\n    if (!handler) {\n      throw new Error('Can\\'t use ' + $conditional);\n    }\n    return handler.call(this, val);\n  }\n  if (val == null) {\n    return val;\n  }\n\n  const Constructor = getConstructor(this.Constructor, val);\n  if (val instanceof Constructor) {\n    return val;\n  }\n\n  if (this.options.runSetters) {\n    val = this._applySetters(val, context);\n  }\n\n  const overrideStrict = options?.strict ?? void 0;\n","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/schema/subdocument.js#L222-L258","documentation":"Single-nested paths support a limited operator set in query casting: the base handlers ($eq, $in, $ne, $nin, $all, $exists, $type) plus geospatial ones ($geoWithin, $near, $nearSphere, $within, $geoIntersects, $minDistance, $maxDistance). Using any other operator directly on the subdocument path makes SchemaSubdocument.castForQuery throw this error while the query is built.","triggerScenarios":"`Model.find({ nested: { $size: 2 } })`; `Model.find({ address: { $regex: /San/ } })` where `address` is an embedded schema; `{ nested: { $gt: { ... } } }`.","commonSituations":"Generic filter builders applying operators to every path; trying to regex-match or range-compare a whole embedded object instead of its subfield.","solutions":["Target the subfield with a dotted path: `Model.find({ 'address.city': /San/ })`","Use `$elemMatch` when querying arrays of subdocuments","For whole-document equality use `$eq` with a plain object of the subdocument's values"],"exampleFix":"// before\nModel.find({ address: { $regex: /San/ } }); // throws: Can't use $regex\n\n// after\nModel.find({ 'address.city': /San/ });","handlingStrategy":"validation","validationCode":"const SUBDOC_OPS = new Set(['$eq','$in','$ne','$nin','$all','$exists','$type','$geoWithin','$geoIntersects','$near','$nearSphere','$within','$minDistance','$maxDistance']);\nfunction assertSubdocOp(op) {\n  if (!SUBDOC_OPS.has(op)) throw new Error(`operator ${op} is not supported on subdocument paths; query subfields with dotted paths`);\n}","typeGuard":"const isSupportedSubdocOp = op => SUBDOC_OPS.has(op);","tryCatchPattern":"try {\n  await Model.find({ nested: { [op]: val } });\n} catch (err) {\n  if (/^Can't use \\$/.test(err.message)) {\n    // rewrite the filter to use a dotted subfield path and retry once\n  } else throw err;\n}","preventionTips":["Prefer dotted paths ('address.city') over operator objects on the embedded path itself","Schema-aware filter builders should know each path's resolved type before attaching operators"],"tags":["mongoose","subdocument","query","operators"],"backgroundTag":"unsupported-query-operator","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}