Automattic/mongoose · error · MongooseError
Base SchemaType class does not implement a `cast()` function
Error message
Base SchemaType class does not implement a `cast()` function
What it means
SchemaType.prototype.cast is an abstract stub that always throws (lib/schemaType.js:379). If you register a custom schematype class that extends mongoose.SchemaType without overriding `cast()`, the first assignment or query cast on that path calls the inherited stub and throws this MongooseError.
Source
Thrown at lib/schemaType.js:379
}
if (message != null) {
this._castErrorMessage = message;
}
return this._castFunction;
};
/**
* The function that Mongoose calls to cast arbitrary values to this SchemaType.
*
* @param {object} value value to cast
* @param {Document} doc document that triggers the casting
* @param {boolean} init
* @api public
*/
SchemaType.prototype.cast = function cast() {
throw new MongooseError('Base SchemaType class does not implement a `cast()` function');
};
/**
* Sets a default option for this schema type.
*
* #### Example:
*
* // Make all strings be trimmed by default
* mongoose.SchemaTypes.String.set('trim', true);
*
* @param {string} option The name of the option you'd like to set (e.g. trim, lowercase, etc...)
* @param {any} value The value of the option you'd like to set.
* @return {void}
* @static
* @memberOf SchemaType
* @function set
* @api public
*/View on GitHub (pinned to 49cdab0136)
Solutions
- Implement `cast(value, doc, init, prev, options)` in the subclass; return the coerced value or throw `new mongoose.Error.CastError('MyType', value, this.path)`
- For a pass-through type, return the value unchanged
- If you only need coercion of an existing type, use a custom caster (e.g. `mongoose.Schema.Types.String.cast(fn)`) instead of a subclass
Example fix
// before
class MyType extends mongoose.SchemaType {
constructor(key, options) { super(key, options, 'MyType'); }
}
// doc.x = 1 -> Base SchemaType class does not implement a `cast()` function
// after
class MyType extends mongoose.SchemaType {
constructor(key, options) { super(key, options, 'MyType'); }
cast(value, doc, init, prev, options) {
if (typeof value !== 'number') {
throw new mongoose.Error.CastError('MyType', value, this.path);
}
return value;
}
} Defensive patterns
Strategy: type-guard
Validate before calling
const assert = require('node:assert');
function registerCustomType(Schema, MyType) {
assert.strictEqual(
MyType.prototype.cast === mongoose.SchemaType.prototype.cast,
false,
'custom schema types must override cast()'
);
Schema.Types.MyType = MyType;
} Type guard
const implementsCast = TypeClass => typeof TypeClass?.prototype?.cast === 'function' && TypeClass.prototype.cast !== mongoose.SchemaType.prototype.cast;
Prevention
- Cover custom schematypes with a unit test that assigns and queries a value (exercises cast)
- Throw CastError (not generic Error) from custom cast implementations for consistent handling
When it happens
Trigger: `class MyType extends mongoose.SchemaType { constructor(key, options) { super(key, options, 'MyType'); } }` with no cast method; `new Schema({ x: { type: MyType } })`; then `doc.x = 1` or any query on `x`.
Common situations: Porting custom-type recipes from older mongoose versions; forgetting the cast override while implementing getters/setters first; accidentally using SchemaType itself as a type.
Related errors
- Query filter must be an object, got an array ${util.inspect(
- Cast to Array failed for value "${value}" at path "${path}"
- Cast to Object failed for value "${value}" at path "${path}.
- Mongoose only supports BigInts between -9223372036854775808
- Cannot convert value to BigInt: "${val}"
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/3ca37e1eac7d9759.
Report an issue: GitHub.