Automattic/mongoose · error · Error
Can't use ${conditional} with UUID.
Error message
Can't use ${conditional} with UUID. What it means
UUID paths support a limited operator set in query casting: the base handlers ($eq, $in, $ne, $nin, $all, $exists, $type) plus the $bitsAllSet/$bitsAnySet/$bitsAllClear/$bitsAnyClear bitwise operators. Any other operator — most commonly $regex or $gt/$lt — has no handler in SchemaUUID.castForQuery and throws this error at query build time.
Source
Thrown at lib/schema/uuid.js:269
Object.defineProperty(SchemaUUID.prototype, '$conditionalHandlers', {
enumerable: false,
value: $conditionalHandlers
});
/**
* Casts contents for queries.
*
* @param {string} $conditional
* @param {any} val
* @api private
*/
SchemaUUID.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 UUID.');
return handler.call(this, val, context);
}
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;
}
};
/**
* Returns this schema type's representation in a JSON schema.
*
* @param {object} [options]
* @param {boolean} [options.useBsonType=false] If true, return a representation with `bsonType` for use with MongoDB's `$jsonSchema`.View on GitHub (pinned to 49cdab0136)
Solutions
- Match full UUIDs with equality (`$eq`/`$in`) instead of partial matching
- If you truly need regex/partial search, keep a separate string shadow field (or use $toString in an aggregation pipeline)
- Remove range/geospatial operators from UUID paths
Example fix
// before
Model.find({ uid: { $regex: /^3f8a/ } }); // throws
// after
Model.find({ uid: '3f8a1c2e-9b4d-4e6a-8f2b-1c9d8e7f6a5b' }); Defensive patterns
Strategy: validation
Validate before calling
const UUID_PATH_OPS = new Set(['$eq','$in','$ne','$nin','$all','$exists','$type','$bitsAllSet','$bitsAnySet','$bitsAllClear','$bitsAnyClear']);
function assertUuidOp(op) {
if (!UUID_PATH_OPS.has(op)) throw new Error(`operator ${op} is not supported on UUID paths; use equality or a string shadow field`);
} Type guard
const isSupportedUuidOp = op => UUID_PATH_OPS.has(op);
Try / catch
try {
await Model.find({ uid: { [op]: val } });
} catch (err) {
if (/^Can't use \$(\w+) with UUID\.$/.test(err.message)) {
// drop the unsupported operator or move partial matching to a string field
} else throw err;
} Prevention
- Treat UUIDs as opaque identifiers: full-value equality only
- For searchable identifiers keep a separate lowercase string field for regex/prefix search
When it happens
Trigger: `Model.find({ uid: { $regex: /ff$/ } })`; `{ uid: { $gt: '0000...' } }`; copy-pasting a string filter onto a UUID path.
Common situations: Search-as-you-type UIs applying regex to every field; range comparisons on UUIDs; generic filter builders ignoring field types.
Related errors
- Can't use ${conditional} with String.
- Can't use ${conditional}
- Can't use ${conditional}
- Invalid addFields() argument. Must be an object
- Query filter must be an object, got an array ${util.inspect(
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/82e64bd35352234b.
Report an issue: GitHub.