Automattic/mongoose · error · MongooseError
You can only add an embedded discriminator on a document arr
Error message
You can only add an embedded discriminator on a document array, ${this.path} is a plain array What it means
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.
Source
Thrown at lib/schema/array.js:477
return value;
}
throw new CastError('Array', util.inspect(value), this.path, null, this);
};
SchemaArray.prototype.$toObject = SchemaArray.prototype.toObject;
/*!
* ignore
*/
SchemaArray.prototype.discriminator = function(...args) {
let arr = this;
while (arr.$isMongooseArray && !arr.$isMongooseDocumentArray) {
arr = arr.embeddedSchemaType;
}
if (!arr.$isMongooseDocumentArray) {
throw new MongooseError('You can only add an embedded discriminator on a document array, ' + this.path + ' is a plain array');
}
return arr.discriminator(...args);
};
/*!
* ignore
*/
SchemaArray.prototype.clone = function() {
const options = Object.assign({}, this.options);
const schematype = new this.constructor(this.path, this.embeddedSchemaType, options, this.schemaOptions, this.parentSchema);
schematype.validators = this.validators.slice();
if (this.requiredValidator !== undefined) {
schematype.requiredValidator = this.requiredValidator;
}
return schematype;
};
View on GitHub (pinned to 49cdab0136)
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.
Example fix
// before
const s = new Schema({ items: [String] });
s.path('items').discriminator('Note', new Schema({ text: String }));
// after
const base = new Schema({ kind: String }, { discriminatorKey: 'kind' });
const s = new Schema({ items: [base] });
s.path('items').discriminator('Note', new Schema({ text: String })); Defensive patterns
Strategy: validation
Validate before calling
const isDocumentArrayPath = (schema, name) =>
schema.path(name)?.$isMongooseDocumentArray === true;
if (!isDocumentArrayPath(schema, 'items')) {
throw new Error('declare items as an array of subdocuments before adding discriminators');
}
schema.path('items').discriminator('Note', noteSchema); Prevention
- 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.
When it happens
Trigger: `schema.path('tags').discriminator('X', sub)` with `tags: [String]`; arrays declared as bare [] (Mixed elements); nested `[[String]]` walking down to a primitive leaf.
Common situations: 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.
Related errors
- Path "${path}" is not an array
- `enum` can only be set on an array of strings or numbers , n
- Cannot set populate virtual as a property of an array
- Cannot have duplicate keys in discriminators with encryption
- Discriminator "${doc[discriminatorKey]}" not found for model
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/770b78a99db330ac.
Report an issue: GitHub.