{"record":{"id":"770b78a99db330ac","repo":"Automattic/mongoose","slug":"you-can-only-add-an-embedded-discriminator-on-a-do","errorCode":null,"errorMessage":"You can only add an embedded discriminator on a document array, ${this.path} is a plain array","messagePattern":"You can only add an embedded discriminator on a document array, (.+?) is a plain array","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/schema/array.js","lineNumber":477,"sourceCode":"    return value;\n  }\n\n  throw new CastError('Array', util.inspect(value), this.path, null, this);\n};\n\nSchemaArray.prototype.$toObject = SchemaArray.prototype.toObject;\n\n/*!\n * ignore\n */\n\nSchemaArray.prototype.discriminator = function(...args) {\n  let arr = this;\n  while (arr.$isMongooseArray && !arr.$isMongooseDocumentArray) {\n    arr = arr.embeddedSchemaType;\n  }\n  if (!arr.$isMongooseDocumentArray) {\n    throw new MongooseError('You can only add an embedded discriminator on a document array, ' + this.path + ' is a plain array');\n  }\n  return arr.discriminator(...args);\n};\n\n/*!\n * ignore\n */\n\nSchemaArray.prototype.clone = function() {\n  const options = Object.assign({}, this.options);\n  const schematype = new this.constructor(this.path, this.embeddedSchemaType, options, this.schemaOptions, this.parentSchema);\n  schematype.validators = this.validators.slice();\n  if (this.requiredValidator !== undefined) {\n    schematype.requiredValidator = this.requiredValidator;\n  }\n  return schematype;\n};\n","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/schema/array.js#L459-L495","documentation":"Calling discriminator() on an array path walks nested arrays down to the document-array schematype ($isMongooseDocumentArray) because embedded discriminators key off each subdocument's discriminatorKey. If the leaf is a plain array of primitives (or nested arrays that never reach subdocuments), there is nothing to discriminate and the call is rejected.","triggerScenarios":"`schema.path('tags').discriminator('X', sub)` with `tags: [String]`; arrays declared as bare [] (Mixed elements); nested `[[String]]` walking down to a primitive leaf.","commonSituations":"Intending polymorphic embedded documents but declaring primitives; refactoring a subdocument array into a primitive array while keeping discriminator registration; example code copied from document-array contexts.","solutions":["Declare the path as a document array: `subs: [new Schema({ kind: String }, { discriminatorKey: 'kind' })]`, then `schema.path('subs').discriminator('X', XSchema)`.","Or register embedded discriminators on the base embedded schema directly.","For primitive arrays, branch in application code instead of discriminators."],"exampleFix":"// before\nconst s = new Schema({ items: [String] });\ns.path('items').discriminator('Note', new Schema({ text: String }));\n\n// after\nconst base = new Schema({ kind: String }, { discriminatorKey: 'kind' });\nconst s = new Schema({ items: [base] });\ns.path('items').discriminator('Note', new Schema({ text: String }));","handlingStrategy":"validation","validationCode":"const isDocumentArrayPath = (schema, name) =>\n  schema.path(name)?.$isMongooseDocumentArray === true;\nif (!isDocumentArrayPath(schema, 'items')) {\n  throw new Error('declare items as an array of subdocuments before adding discriminators');\n}\nschema.path('items').discriminator('Note', noteSchema);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare an explicit embedded schema for arrays that will host discriminators - never bare [] or [String].","Register embedded discriminators in the same module that declares the base embedded schema.","Set discriminatorKey on the base embedded schema so dispatch is explicit."],"tags":["discriminators","arrays","embedded-documents","schema-definition"],"backgroundTag":"embedded-discriminator-misuse","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}