{"record":{"id":"3d8ce328ffc59079","repo":"Automattic/mongoose","slug":"discriminator-doc-discriminatorkey-not-found","errorCode":null,"errorMessage":"Discriminator \"${doc[discriminatorKey]}\" not found for model \"${this.modelName}\"","messagePattern":"Discriminator \"(.+?)\" not found for model \"(.+?)\"","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":2756,"sourceCode":"    return Array.isArray(doc) ? [] : null;\n  }\n  let res = [];\n  const immediateError = typeof options.aggregateErrors === 'boolean' ? !options.aggregateErrors : true;\n\n  delete options.aggregateErrors; // dont pass on the option to \"$save\"\n\n  if (options.session && !options.ordered && args.length > 1) {\n    throw new MongooseError('Cannot call `create()` with a session and multiple documents unless `ordered: true` is set');\n  }\n\n  if (!Array.isArray(doc) && args.length === 1) {\n    let toSave = doc;\n\n    const Model = this.discriminators && doc[discriminatorKey] != null ?\n      this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :\n      this;\n    if (Model == null) {\n      throw new MongooseError(`Discriminator \"${doc[discriminatorKey]}\" not ` +\n      `found for model \"${this.modelName}\"`);\n    }\n\n    if (!(toSave instanceof Model)) {\n      toSave = new Model(toSave);\n    }\n\n    await toSave.$save(options);\n\n    return toSave;\n  }\n\n  if (options.ordered) {\n    for (let i = 0; i < args.length; i++) {\n      try {\n        const doc = args[i];\n        const Model = this.discriminators && doc[discriminatorKey] != null ?\n          this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this.discriminators, doc[discriminatorKey]) :","sourceCodeStart":2738,"sourceCodeEnd":2774,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L2738-L2774","documentation":"When creating a single document (non-array form of Model.create()), Mongoose resolves the concrete model by looking up doc[discriminatorKey] (default '__t') in this.discriminators, falling back to getDiscriminatorByValue() for value-based discriminators. If the model has discriminators registered and the stored value matches neither a discriminator name nor a registered mapping value, Model resolves to null and this MongooseError is thrown.","triggerScenarios":"BaseModel.create({ __t: 'Typo', ... }) where 'Typo' was never registered via Base.discriminator('Typo', schema); value-based discriminators created without a matching { value } option; data deserialized from a queue/another service carrying an unknown __t.","commonSituations":"Typos or case mismatches in the discriminator key value ('click' vs 'Click'); renaming or removing a discriminator while old clients still send the old __t; value-based discriminators where a numeric/enum value was not registered; test fixtures referencing discriminators that were moved to another base.","solutions":["Register the missing discriminator on the base model: Base.discriminator('Click', ClickSchema) (with { value: 1 } for value-based discriminators) before create() runs","Fix the discriminator key value in the input document to exactly match a registered discriminator name or value (lookup is case-sensitive)","If the unknown key means 'use the base model', delete it before creating: delete doc.__t (a null/undefined key routes to this/base model)","If stale __t values are expected from legacy data, strip or remap them in a pre-save hook or sanitize step before calling create()"],"exampleFix":"// before\nEvent.create({ __t: 'clic', kind: 'x' }); // throws: Discriminator \"clic\" not found\n\n// after\nEvent.discriminator('click', ClickSchema);\nawait Event.create({ __t: 'click', kind: 'x' });","handlingStrategy":"validation","validationCode":"function hasKnownDiscriminator(Model, doc) {\n  const key = Model.schema.options.discriminatorKey; // default '__t'\n  const value = doc?.[key];\n  if (value == null || !Model.discriminators) return true; // routes to base model\n  if (Model.discriminators[value] != null) return true; // by name\n  return Object.values(Model.discriminators).some(D =>\n    D.schema?.discriminatorMapping &&\n    D.schema.discriminatorMapping.value === value // value-based\n  );\n}\n// if (!hasKnownDiscriminator(Base, doc)) throw new Error(`unknown ${Base.modelName} discriminator`);","typeGuard":null,"tryCatchPattern":"try {\n  const doc = await Base.create(payload);\n} catch (err) {\n  if (err instanceof mongoose.MongooseError && /^Discriminator \".*\" not found/.test(err.message)) {\n    // bad discriminator key from upstream data: reject payload or fall back to base\n    delete payload.__t;\n    return Base.create(payload);\n  }\n  throw err;\n}","preventionTips":["Whitelist allowed discriminator values at the API boundary and reject unknown ones early","Centralize discriminator registration in one module imported before any create/insertOne","After renaming/removing a discriminator, grep data producers for the old __t value"],"tags":["mongoose","discriminators","schema","create","polymorphism"],"backgroundTag":"unknown-discriminator-value","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}