{"record":{"id":"70be0d5da49d6f01","repo":"n8n-io/n8n","slug":"403","errorCode":"403","errorMessage":"This account is managed via environment variables and cannot be modified through the API","messagePattern":"This account is managed via environment variables and cannot be modified through the API","errorType":"exception","errorClass":"ForbiddenError","httpStatus":403,"severity":"warning","filePath":"packages/cli/src/controllers/me.controller.ts","lineNumber":202,"sourceCode":"\t\treturn authIdentity.providerType === getCurrentAuthenticationMethod();\n\t}\n\n\t/**\n\t * Update the logged-in user's password.\n\t */\n\t@Patch('/password', {\n\t\tkeyedRateLimit: createUserKeyedRateLimiter({}),\n\t})\n\tasync updatePassword(\n\t\treq: AuthenticatedRequest,\n\t\tres: Response,\n\t\t@Body payload: PasswordUpdateRequestDto,\n\t) {\n\t\tconst { user } = req;\n\t\tconst { currentPassword, newPassword, mfaCode } = payload;\n\n\t\tif (this.isUserManagedByEnv(user)) {\n\t\t\tthrow new ForbiddenError(\n\t\t\t\t'This account is managed via environment variables and cannot be modified through the API',\n\t\t\t);\n\t\t}\n\n\t\t// If SAML is enabled, we don't allow the user to change their password\n\t\tif (isSamlLicensedAndEnabled()) {\n\t\t\tthis.logger.debug('Attempted to change password for user, while SAML is enabled', {\n\t\t\t\tuserId: user.id,\n\t\t\t});\n\t\t\tthrow new BadRequestError(\n\t\t\t\t'With SAML enabled, users need to use their SAML provider to change passwords',\n\t\t\t);\n\t\t}\n\n\t\tif (!user.password) {\n\t\t\tthrow new BadRequestError('Requesting user not set up.');\n\t\t}\n","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/me.controller.ts#L184-L220","documentation":"A ForbiddenError (HTTP 403) from the PATCH /me/password (updatePassword) handler when isUserManagedByEnv(user) returns true. The owner account is pinned to environment variables, so its password cannot be rotated through the API — it must be changed via env config and a restart. Returns 403 because configuration forbids the mutation.","triggerScenarios":"PATCH /me/password for the owner user when ownerManagedByEnv is enabled and the user's email matches the configured owner email. Checked first, before the SAML and password-comparison guards.","commonSituations":"GitOps/Docker deployments that fix the owner via N8N_OWNER_EMAIL/PASSWORD env vars; an operator tries to change the owner password through the UI; env-managed owner where the password field is governed by N8N_OWNER_PASSWORD.","solutions":["Rotate the owner password by updating the relevant environment variable and restarting n8n.","Disable ownerManagedByEnv to allow API-based password changes for the owner.","Use a non-owner account for API-driven password rotation."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Detect env-managed owner before allowing password change.\nconst me = await api.get('/me');\nif (me.flags?.ownerManagedByEnv && me.role === 'global:owner') {\n  throw new Error('Owner password is env-managed; rotate via environment variables.');\n}","typeGuard":"function isEnvManagedOwner(u: { role: string }, cfg: { ownerManagedByEnv: boolean }): boolean {\n  return cfg.ownerManagedByEnv && u.role === 'global:owner';\n}","tryCatchPattern":"try {\n  await api.patch('/me/password', payload);\n} catch (e) {\n  if (e.response?.status === 403 && /environment variables/i.test(e.response.data.message)) {\n    notify('Rotate the owner password via environment variables.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Hide the password-change form for the env-managed owner.","Document the env vars that govern the owner password.","Rotate env-managed secrets through your secrets manager, not the API."],"tags":["me","password","env-config","forbidden","owner"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}