{"record":{"id":"9353aa690e868950","repo":"Automattic/mongoose","slug":"path-path-is-immutable-and-strict-mode-is-set","errorCode":null,"errorMessage":"Path `${path}` is immutable and strict mode is set to throw.","messagePattern":"Path `(.+?)` is immutable and strict mode is set to throw\\.","errorType":"exception","errorClass":"StrictModeError","httpStatus":null,"severity":"error","filePath":"lib/helpers/schematype/handleImmutable.js","lineNumber":44,"sourceCode":"    if (this.isNew) {\n      return v;\n    }\n    if (options?.overwriteImmutable) {\n      return v;\n    }\n\n    const _immutable = typeof immutable === 'function' ?\n      immutable.call(this, this) :\n      immutable;\n    if (!_immutable) {\n      return v;\n    }\n\n    const _value = this.$__.priorDoc != null ?\n      this.$__.priorDoc.$__getValue(path) :\n      this.$__getValue(path);\n    if (this.$__.strictMode === 'throw' && v !== _value) {\n      throw new StrictModeError(path, 'Path `' + path + '` is immutable ' +\n        'and strict mode is set to throw.', true);\n    }\n\n    return _value;\n  };\n}\n","sourceCodeStart":26,"sourceCodeEnd":51,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/helpers/schematype/handleImmutable.js#L26-L51","documentation":"Document-level counterpart of the update-side immutable guard: assigning to a path declared immutable: true on a persisted (non-new) document is normally silently ignored (the previous value is kept). If the document's strict mode is 'throw' and the new value differs from the stored prior value, the immutable setter throws this StrictModeError instead. Immutable paths are write-once: set at creation, unchangeable on loaded documents.","triggerScenarios":"doc.name = 'new' or doc.set('name', 'new') where the schema declares name: { type: String, immutable: true }, the document was loaded from the DB (isNew false, priorDoc exists), and the schema (or document) uses strict: 'throw'.","commonSituations":"Generic form handlers that assign every submitted field onto a loaded document; schemas hardened with strict:'throw'; write-once fields like username, email, or tenant id edited after onboarding; bulk import scripts mutating loaded docs.","solutions":["Skip assignment to immutable paths when updating existing documents (check doc.isNew or the schema path's immutable option)","If the field must be editable, remove immutable: true or make it conditional with a function (immutable: function() { ... })","Force an intentional change through the query layer: Model.updateOne({ _id: doc._id }, { $set: { name: 'new' } }, { overwriteImmutable: true })","Re-create the document instead of mutating an immutable field on a loaded one"],"exampleFix":"// before\nconst user = await User.findById(id);\nuser.email = req.body.email; // email is immutable, strict: 'throw' -> throws\nawait user.save();\n\n// after\nconst user = await User.findById(id);\nuser.displayName = req.body.displayName; // mutable\nawait user.save();","handlingStrategy":"validation","validationCode":"// Skip assignment of immutable paths on loaded documents\nfunction assignMutable(doc, patch) {\n  const schema = doc.schema;\n  for (const [k, v] of Object.entries(patch)) {\n    if (!doc.isNew && schema.path(k)?.options?.immutable) continue;\n    doc.set(k, v);\n  }\n}","typeGuard":"const isImmutablePath = (schema, path) => Boolean(schema.path(path)?.options?.immutable);","tryCatchPattern":"try {\n  doc.set('name', value);\n  await doc.save();\n} catch (err) {\n  if (err instanceof mongoose.Error.StrictModeError && /immutable/.test(err.message)) {\n    // reject the edit or route through Model.updateOne(..., { overwriteImmutable: true })\n  } else throw err;\n}","preventionTips":["Map PATCH endpoints to explicit mutable field lists instead of assigning whole bodies","Make immutability conditional (immutable: () => cond) when a field is editable in some flows","Test edit flows against strict:'throw' schemas in CI so violations surface early"],"tags":["mongoose","immutable","strict-mode","document","setters"],"backgroundTag":"immutable-field-violation","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}