Automattic/mongoose · error · CastError

Cast to Embedded failed for value "${value}" (type ${valueTy

Error message

Cast to Embedded failed for value "${value}" (type ${valueType}) at path "${path}"

What it means

When casting a query/update value into a single-nested subdocument, mongoose runs `new Constructor(val)`. Any failure that is not already a CastError is wrapped as `Cast to Embedded failed ... at path` (gh-6803) so callers always get a CastError; the underlying error is preserved on `err.reason`.

Source

Thrown at lib/schema/subdocument.js:264

  }

  const Constructor = getConstructor(this.Constructor, val);
  if (val instanceof Constructor) {
    return val;
  }

  if (this.options.runSetters) {
    val = this._applySetters(val, context);
  }

  const overrideStrict = options?.strict ?? void 0;

  try {
    val = new Constructor(val, overrideStrict);
  } catch (error) {
    // Make sure we always wrap in a CastError (gh-6803)
    if (!(error instanceof CastError)) {
      throw new CastError('Embedded', val, this.path, error, this);
    }
    throw error;
  }
  return val;
};

/**
 * Async validation on this single nested doc.
 *
 * @api public
 */

SchemaSubdocument.prototype.doValidate = async function doValidate(value, scope, options) {
  const Constructor = getConstructor(this.Constructor, value);

  if (value && !(value instanceof Constructor)) {
    value = new Constructor(value, null, scope?.$__ != null ? scope : null);
  }

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Pass a plain object (or query the subfield with a dotted path) instead of a primitive
  2. Inspect `err.reason` and the original message to find the real failure inside the subschema
  3. Fix or make exception-safe any custom setter/transform on the subschema that throws non-CastError errors
  4. Cast the value yourself (`new Subdoc(value)`) inside try/catch to surface the raw error during development

Example fix

// before
Model.find({ nested: 'x' }); // throws Cast to Embedded failed

// after
Model.find({ 'nested.name': 'x' }); // query the subfield directly
Defensive patterns

Strategy: try-catch

Validate before calling

function isCastableSubdocValue(v) {
  return v == null || (typeof v === 'object' && !Array.isArray(v));
}

Type guard

const isCastableSubdocValue = v => v == null || (typeof v === 'object' && !Array.isArray(v));

Try / catch

try {
  const docs = await Model.find({ nested: raw });
} catch (err) {
  if (err instanceof mongoose.Error.CastError && err.kind === 'Embedded') {
    const root = err.reason; // underlying constructor/setter failure
    // reject the request payload and include err.path + root.message in diagnostics
  } else throw err;
}

Prevention

When it happens

Trigger: `Model.find({ nested: 'not-an-object' })` where the value cannot be constructed into the subschema; custom setters on the subschema that throw TypeErrors during construction; `$set` updates with values the subdocument constructor rejects.

Common situations: Passing primitives where objects are expected in filters; discriminator construction mismatches; bugs in custom setters that only surface during query casting.

Related errors


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