Automattic/mongoose · error · ObjectExpectedError

Tried to set nested object field `${path}` to ${typeDescript

Error message

Tried to set nested object field `${path}` to ${typeDescription} `${val}`

What it means

ObjectExpectedError thrown by SchemaSubdocument.cast when a non-null value that is not an object (a string, number, boolean) or is an array is assigned to a single-nested ('embedded') path during a document set (not on init from the database). Mongoose requires a plain object it can cast into the subschema.

Source

Thrown at lib/schema/subdocument.js:183

Object.defineProperty(SchemaSubdocument.prototype, '$conditionalHandlers', {
  enumerable: false,
  value: $conditionalHandlers
});

/**
 * Casts contents
 *
 * @param {object} value
 * @api private
 */

SchemaSubdocument.prototype.cast = function(val, doc, init, priorVal, options) {
  if (val?.$isSingleNested && val.parent === doc) {
    return val;
  }

  if (!init && val != null && (typeof val !== 'object' || Array.isArray(val))) {
    throw new ObjectExpectedError(this.path, val);
  }

  const discriminatorKeyPath = this.schema.path(this.schema.options.discriminatorKey);
  const defaultDiscriminatorValue = discriminatorKeyPath == null ? null : discriminatorKeyPath.getDefault(doc);
  const Constructor = getConstructor(this.Constructor, val, defaultDiscriminatorValue);

  let subdoc;

  // Only pull relevant selected paths and pull out the base path
  const parentSelected = doc?.$__?.selected;
  const path = this.path;
  const selected = parentSelected == null ? null : Object.keys(parentSelected).reduce((obj, key) => {
    if (key.startsWith(path + '.')) {
      obj = obj || {};
      obj[key.substring(path.length + 1)] = parentSelected[key];
    }
    return obj;
  }, null);

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Assign a plain object matching the subschema: `doc.child = { name: 'A' }`
  2. JSON.parse the value first if the source sends serialized JSON
  3. If a list was intended, declare the path as `type: [childSchema]` instead of a single subdocument

Example fix

// before
doc.child = '{"name":"A"}'; // string, throws

// after
doc.child = JSON.parse('{"name":"A"}'); // plain object
Defensive patterns

Strategy: validation

Validate before calling

function isPlainObject(v) {
  return v != null && typeof v === 'object' && !Array.isArray(v);
}
if (!isPlainObject(payload.child)) payload.child = JSON.parse(payload.child); // or reject

Type guard

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

Try / catch

try {
  doc.child = value;
} catch (err) {
  if (err.name === 'ObjectExpectedError') {
    // value was a primitive/array where an object was expected; reject or coerce
  } else throw err;
}

Prevention

When it happens

Trigger: `doc.child = 'oops'` where `child` is defined as `new Schema({ name: String })`; `Model.updateOne({}, { $set: { child: 42 } })`; assigning a JSON.stringify'd string where the object was expected.

Common situations: API payloads where the nested field arrives as stringified JSON; form data always being strings; assigning an array to a single-nested field when an array-of-subdocs schema was intended.

Related errors


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