Automattic/mongoose · error · Error
Can't use ${$conditional} with Date.
Error message
Can't use ${$conditional} with Date. What it means
castForQuery on a Date path throws a plain Error when the filter uses an operator with no registered handler. Date supports $gt/$gte/$lt/$lte plus the base SchemaType handlers ($in, $nin, $ne, $exists, ...); operators like $regex, $mod, $all, or a typo'd operator reach the guard.
Source
Thrown at lib/schema/date.js:441
* @api private
*/
SchemaDate.prototype.castForQuery = function($conditional, val, context) {
if ($conditional == null) {
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;
}
}
const handler = this.$conditionalHandlers[$conditional];
if (!handler) {
throw new Error('Can\'t use ' + $conditional + ' with Date.');
}
return handler.call(this, val);
};
/**
* 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`.
* @returns {object} JSON schema properties
*/
SchemaDate.prototype.toJSONSchema = function toJSONSchema(options) {
return this._createJSONSchemaTypeDefinition('string', 'date', options);
};
SchemaDate.prototype.autoEncryptionType = function autoEncryptionType() {View on GitHub (pinned to 49cdab0136)
Solutions
- Use range operators for dates: `{ createdAt: { $gte: from, $lte: to } }`
- For string matching on dates, project a formatted string (aggregation `$dateToString`) or store a separate string field
- Whitelist operators per field type in dynamic query builders
- Catch the Error and map it to a 400 with the offending operator name
Example fix
// before
Model.find({ createdAt: { $regex: '^2024-01' } });
// after
Model.find({ createdAt: { $gte: new Date('2024-01-01'), $lt: new Date('2024-02-01') } }); Defensive patterns
Strategy: validation
Validate before calling
const DATE_OPS = new Set(['$gt','$gte','$lt','$lte','$in','$nin','$ne','$eq','$exists','$not']);
function assertDateOpsSafe(pathFilter, path) {
for (const op of Object.keys(pathFilter ?? {})) {
if (op.startsWith('$') && !DATE_OPS.has(op)) throw new Error(`operator ${op} not allowed on date path ${path}`);
}
} Try / catch
try { await Model.find(filter); } catch (err) { if (/Can't use .* with Date/.test(err.message)) { throw Object.assign(new Error(`unsupported date operator: ${err.message}`), { status: 400 }); } throw err; } Prevention
- Offer only range filters for date fields in search UIs
- Convert date-regex intents into $gte/$lte ranges
- Test dynamic filter endpoints against every field type
When it happens
Trigger: `Model.find({ createdAt: { $regex: '^2024' } })`, `Model.find({ d: { $size: 2 } })`, or any `{ <datePath>: { $<op>: ... } }` where $op is not in SchemaDate's $conditionalHandlers. Date-range aggregations accidentally putting $expr-style operators inside a path filter also hit it.
Common situations: Copy-pasting a String-path regex filter onto a timestamp field; dynamic search UIs that offer 'contains' for every field including dates; typo'd operators ($gte vs $gt); sift.js-style operators ($between) sent straight to MongoDB paths.
Related errors
- Can't use ${$conditional} with Buffer.
- Can't use ${conditional} with Number.
- Query filter must be an object, got an array ${util.inspect(
- Cast to number failed for value "${value}" (type ${valueType
- Invalid addFields() argument. Must be an object
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/510af2a04235ec94.
Report an issue: GitHub.