{"record":{"id":"58314ce926bb5981","repo":"Automattic/mongoose","slug":"cast-to-embedded-failed-for-value-value-type","errorCode":null,"errorMessage":"Cast to embedded failed for value \"${value}\" (type ${valueType}) at path \"${path}\"","messagePattern":"Cast to embedded failed for value \"(.+?)\" \\(type (.+?)\\) at path \"(.+?)\"","errorType":"exception","errorClass":"CastError","httpStatus":null,"severity":"error","filePath":"lib/schema/documentArray.js","lineNumber":492,"sourceCode":"        if (typeof prev?.id === 'function') {\n          subdoc = prev.id(rawArray[i]._id);\n        }\n\n        if (prev && subdoc && utils.deepEqual(subdoc.toObject(_toObjectOptions), rawArray[i])) {\n          // handle resetting doc with existing id and same data\n          subdoc.set(rawArray[i]);\n          // if set() is hooked it will have no return value\n          // see gh-746\n          rawArray[i] = subdoc;\n        } else {\n          try {\n            subdoc = new Constructor(rawArray[i], value, undefined,\n              undefined, i);\n            // if set() is hooked it will have no return value\n            // see gh-746\n            rawArray[i] = subdoc;\n          } catch (error) {\n            throw new CastError('embedded', rawArray[i],\n              value[arrayPathSymbol], error, this);\n          }\n        }\n      }\n    }\n  }\n\n  return value;\n};\n\n/*!\n * ignore\n */\n\nSchemaDocumentArray.prototype.clone = function() {\n  const options = Object.assign({}, this.options);\n  const schematype = new this.constructor(\n    this.path,","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/schema/documentArray.js#L474-L510","documentation":"While casting each element of a document array, Mongoose constructs a subdocument (`new Constructor(element, ...)`) and wraps any construction failure as `CastError: embedded` pointing at the array path. So one element of your subdocument array could not be turned into a subdocument: typically a primitive element (string/number/array) where a plain object is required, or an element whose own nested casting threw during subdocument creation.","triggerScenarios":"`doc.items = [{ name: 'ok' }, 'oops']` — array elements that are strings, numbers, or nested arrays instead of plain objects; update operations pushing malformed values (`$push: { items: 'oops' }`); import pipelines feeding mixed rows. The original failure is preserved on the error's `reason` property (and `originalError` fields), which names the real cause.","commonSituations":"CSV/JSON imports where some rows are scalars or null-ish sentinels; APIs returning heterogeneous arrays; mapping over unvalidated external data into embedded arrays; spread operator bugs that flatten objects into unexpected shapes.","solutions":["Inspect `err.reason` on the CastError — it carries the underlying error and tells you which element shape failed","Filter/normalize to plain objects before assignment: `arr.filter(v => utils.isPOJO(v))` or map primitives into `{ value: v }`","Validate each row against the subschema (validateSync on a scratch document, or ajv) before bulk-inserting","Add per-element schema validation (e.g. `validate: { validator: v => v != null && typeof v === 'object' }`) to fail with a clearer message"],"exampleFix":"// before\ndoc.items = importedRows; // some rows are plain strings\n\n// after\ndoc.items = importedRows\n  .filter(r => r && typeof r === 'object' && !Array.isArray(r))\n  .map(r => ({ name: String(r.name ?? '') }));","handlingStrategy":"validation","validationCode":"function sanitizeDocArray(rows) {\n  return (Array.isArray(rows) ? rows : []).filter(\n    r => r != null && typeof r === 'object' && !Array.isArray(r)\n  );\n}\ndoc.items = sanitizeDocArray(importedRows);","typeGuard":"function isPlainObjectRow(v) {\n  return v != null && typeof v === 'object' && !Array.isArray(v) && !(v instanceof Date) && !Buffer.isBuffer(v);\n}","tryCatchPattern":"try { doc.items = rows; } catch (err) { if (err.name === 'CastError' && err.kind === 'embedded') { console.error('element failed:', err.reason?.message); return badRequest(`invalid element in ${err.path}`); } throw err; }","preventionTips":["Filter imports to plain-object rows before assigning","Read err.reason — it names the underlying failure","Add per-element validators that reject primitives with clear messages"],"tags":["mongoose","embedded-document","document-array","cast","subdocument"],"backgroundTag":"mongoose-cast-error","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}