{"record":{"id":"1fc02e5bc8e8d8c1","repo":"Automattic/mongoose","slug":"can-t-use-conditional-1fc02e","errorCode":null,"errorMessage":"Can't use ${conditional}","messagePattern":"Can't use (.+?)","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/schemaType.js","lineNumber":1813,"sourceCode":"  $type: $type\n};\n\n/**\n * Cast the given value with the given optional query operator.\n *\n * @param {string} [$conditional] query operator, like `$eq` or `$in`\n * @param {any} val\n * @param {Query} context\n * @return {any}\n * @api private\n */\n\nSchemaType.prototype.castForQuery = function($conditional, val, context) {\n  let handler;\n  if ($conditional != null) {\n    handler = this.$conditionalHandlers[$conditional];\n    if (!handler) {\n      throw new MongooseError('Can\\'t use ' + $conditional);\n    }\n    return handler.call(this, val, context);\n  }\n\n  try {\n    return this.applySetters(val, context);\n  } catch (err) {\n    if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {\n      err.path = this.$fullPath;\n    }\n    throw err;\n  }\n};\n\n/**\n * Set & Get the `checkRequired` function\n * Override the function the required validator uses to check whether a value\n * passes the `required` check. Override this on the individual SchemaType.","sourceCodeStart":1795,"sourceCodeEnd":1831,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/schemaType.js#L1795-L1831","documentation":"Thrown by SchemaType.prototype.castForQuery() when a query uses a $conditional operator that has no handler registered on this schematype's $conditionalHandlers. Each path type supports a fixed set of operators; using one outside that set (typo or genuinely unsupported for the type) is rejected.","triggerScenarios":"Model.find({ age: { $regex: /18/ } }) on a Number path ($regex has no handler for numbers); a typo like { $ga: 5 } instead of $gt; using $all or $elemMatch on a plain scalar path; passing an operator name directly via castForQuery.","commonSituations":"Changing a field from String to Number/ObjectId while old queries still use $regex/$options; dynamically building filters from user input that includes arbitrary operator keys; copy-pasting MongoDB shell queries into Mongoose.","solutions":["Fix the operator typo and use standard MongoDB query operators ($gt, $in, $eq, $ne, ...)","Match the operator to the path type: no $regex on Number/Date/Boolean paths — query by exact value or $in instead","If the field must be searched by pattern, store it as String in the schema","For genuinely custom operators, register a handler on the type's $conditionalHandlers before building the query"],"exampleFix":"// before (age is a Number path)\nModel.find({ age: { $regex: /^18/ } });\n// after\nModel.find({ age: { $gte: 18, $lt: 19 } });","handlingStrategy":"validation","validationCode":"const OPS = new Set(['$eq','$ne','$gt','$gte','$lt','$lte','$in','$nin','$exists','$regex','$options','$all','$size','$elemMatch','$not','$near','$within','$geoWithin','$geoIntersects','$center','$centerSphere','$box','$polygon','$maxDistance','$mod','$type','$bitsAllSet','$comment']);\nfunction validateFilter(filter) {\n  for (const v of Object.values(filter)) {\n    if (v && typeof v === 'object' && !Array.isArray(v)) {\n      for (const op of Object.keys(v)) {\n        if (op.startsWith('$') && !OPS.has(op)) throw new Error(`Unsupported operator: ${op}`);\n      }\n    }\n  }\n}","typeGuard":"function isKnownOperator(op) { return /^\\$/.test(op) && KNOWN_OPS_FOR_TYPE.has(op); }","tryCatchPattern":"try { const docs = await Model.find(filter); } catch (err) { if (/Can't use/.test(err.message)) throw new Error(`Bad operator in filter: ${err.message}`); throw err; }","preventionTips":["Validate dynamically built filters against an operator allowlist before querying","Keep operator usage aligned with the declared schema type (no $regex on Number paths)","Add integration tests per query helper so typos surface in CI"],"tags":["mongoose","query","operators","cast-for-query"],"backgroundTag":"unsupported-query-operator","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}