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

  1. Implement `cast(value, doc, init, prev, options)` in the subclass; return the coerced value or throw `new mongoose.Error.CastError('MyType', value, this.path)`
  2. For a pass-through type, return the value unchanged
  3. 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

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


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/3ca37e1eac7d9759. Report an issue: GitHub.