Automattic/mongoose · error · Error
Can't use ${conditional} with String.
Error message
Can't use ${conditional} with String. What it means
When a query applies an operator to a String path, mongoose looks it up in SchemaString's `$conditionalHandlers`, which supports $eq, $gt, $gte, $in, $lt, $lte, $ne, $nin, $all, $exists, $type, $regex, $options, and $not. Any other operator (geospatial operators, $size, $mod, or a typo) has no handler and `castForQuery` throws during query building.
Source
Thrown at lib/schema/string.js:694
Object.defineProperty(SchemaString.prototype, '$conditionalHandlers', {
enumerable: false,
value: $conditionalHandlers
});
/**
* Casts contents for queries.
*
* @param {string} $conditional
* @param {any} [val]
* @api private
*/
SchemaString.prototype.castForQuery = function($conditional, val, context) {
let handler;
if ($conditional != null) {
handler = this.$conditionalHandlers[$conditional];
if (!handler) {
throw new Error('Can\'t use ' + $conditional + ' with String.');
}
return handler.call(this, val, context);
}
if (Object.prototype.toString.call(val) === '[object RegExp]' || isBsonType(val, 'BSONRegExp')) {
return val;
}
try {
return this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
};
View on GitHub (pinned to 49cdab0136)
Solutions
- Move the operator to a path of the matching type (e.g. $size on an array path, $near on a 2dsphere path)
- Fix typos in operator keys, especially when built dynamically
- Whitelist per-type operators in generic filter builders
- Use $regex (or $eq) for string matching instead of unsupported operators
Example fix
// before
Model.find({ name: { $size: 3 } }); // 'name' is String
// after
Model.find({ tags: { $size: 3 } }); // 'tags' is an array path Defensive patterns
Strategy: validation
Validate before calling
const STRING_PATH_OPS = new Set(['$eq','$gt','$gte','$in','$lt','$lte','$ne','$nin','$all','$exists','$type','$regex','$options','$not']);
function assertStringOp(op) {
if (!STRING_PATH_OPS.has(op)) throw new Error(`operator ${op} is not supported on String paths`);
} Type guard
const isSupportedStringOp = op => STRING_PATH_OPS.has(op);
Try / catch
try {
await Model.find(filter);
} catch (err) {
if (/^Can't use \$(\w+) with String\.$/.test(err.message)) {
// operator unsupported on this path: reject filter or move it to the right path type
} else throw err;
} Prevention
- Keep a per-type operator whitelist in generic filter builders
- Run geospatial/array operators only on paths whose schema type supports them
- Dry-run dynamic filters with a schema introspection pass before executing
When it happens
Trigger: `Model.find({ name: { $size: 3 } })` (string path); `Model.find({ name: { $near: { $geometry: ... } } })`; typo `{ name: { $regexx: /x/ } }`.
Common situations: Copy-pasting geospatial or array queries onto text fields; generic filter-builder UIs that attach any operator to any path; dynamic operator keys with spelling mistakes.
Related errors
- Cast to string failed for value "${value}" (type ${valueType
- Can't use ${conditional}
- Can't use ${conditional} with UUID.
- Can't use ${conditional}
- Invalid addFields() argument. Must be an object
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/9f2d2fb2e70b5416.
Report an issue: GitHub.