{"record":{"id":"eda87f0e9278c4bf","repo":"Automattic/mongoose","slug":"can-t-use-conditional-with-array","errorCode":null,"errorMessage":"Can't use ${$conditional} with Array.","messagePattern":"Can't use (.+?) with Array\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/schema/array.js","lineNumber":544,"sourceCode":"  return val;\n};\n\n/**\n * Casts values for queries.\n *\n * @param {string} $conditional\n * @param {any} [value]\n * @api private\n */\n\nSchemaArray.prototype.castForQuery = function($conditional, val, context) {\n  let handler;\n\n  if ($conditional != null) {\n    handler = this.$conditionalHandlers[$conditional];\n\n    if (!handler) {\n      throw new Error('Can\\'t use ' + $conditional + ' with Array.');\n    }\n\n    return handler.call(this, val, context);\n  } else {\n    return this._castForQuery(val, context);\n  }\n};\n\n/**\n * Add a virtual to this array. Specifically to this array, not the individual elements.\n *\n * @param {string} name\n * @param {object} [options]\n * @api private\n */\n\nSchemaArray.prototype.virtual = function virtual(name, options) {\n  if (name instanceof VirtualType || getConstructorName(name) === 'VirtualType') {","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/schema/array.js#L526-L562","documentation":"castForQuery on an array path dispatches the query operator to the array type's $conditionalHandlers; an operator with no handler (unsupported at field level for arrays, or a typo like $in2) throws immediately instead of sending an uncastable filter to the server.","triggerScenarios":"`Model.find({ tags: { $regex: 'x' } })` where tags: [String] - $regex has no array-level handler; `{ nums: { $nearSphere: [1,2] } }` on a non-geo array; a misspelled operator echoed verbatim in the message.","commonSituations":"Porting scalar-field query syntax onto array fields; assuming every MongoDB operator is valid per-field; operators that only work at the filter's top level used under a field.","solutions":["Use operators the array type registers (e.g. $in, $nin, $ne, $all, $elemMatch, $options, geo handlers on geo arrays).","Match elements via $elemMatch: `{ tags: { $elemMatch: { $regex: /^x/ } } }` or dot-notation element queries.","Fix operator typos - the message contains the exact operator string."],"exampleFix":"// before\nModel.find({ tags: { $regex: /^admin/ } });\n\n// after\nModel.find({ tags: { $elemMatch: { $regex: /^admin/ } } });\n// or exact-element match:\nModel.find({ tags: 'admin' });","handlingStrategy":"validation","validationCode":"const ARRAY_FIELD_OPERATORS = new Set(['$in', '$nin', '$ne', '$all', '$elemMatch', '$options', '$size', '$exists', '$near', '$nearSphere', '$geoWithin', '$geoIntersects']);\nconst assertArrayFieldFilter = (filter) => {\n  for (const [k, v] of Object.entries(filter)) {\n    if (k.startsWith('$') && !ARRAY_FIELD_OPERATORS.has(k)) {\n      throw new Error(`operator ${k} is not supported directly on an array field`);\n    }\n  }\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer $elemMatch for element-level predicates on array paths.","Keep a shared allow-list of operators your query builder emits and test filters against a local mongoose instance.","The message echoes the operator verbatim - read it to catch typos like $in2."],"tags":["query","operators","arrays","cast-error"],"backgroundTag":"unsupported-query-operator","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}