{"record":{"id":"17fb25875586b9ff","repo":"n8n-io/n8n","slug":"saml-user-may-not-change-their-email","errorCode":null,"errorMessage":"SAML user may not change their email","messagePattern":"SAML user may not change their email","errorType":"exception","errorClass":"BadRequestError","httpStatus":400,"severity":"warning","filePath":"packages/cli/src/controllers/me.controller.ts","lineNumber":137,"sourceCode":"\n\tprivate async validateChangingUserEmail(currentUser: User, payload: UserUpdateRequestDto) {\n\t\tif (!payload.email || payload.email === currentUser.email) {\n\t\t\t// email is not being changed\n\t\t\treturn;\n\t\t}\n\t\tconst { currentPassword: providedCurrentPassword, ...payloadWithoutPassword } = payload;\n\t\tconst { id: userId, mfaEnabled } = currentUser;\n\n\t\t// If SAML is enabled, we don't allow the user to change their email address\n\t\tif (isSamlLicensedAndEnabled()) {\n\t\t\tthis.logger.debug(\n\t\t\t\t'Request to update user failed because SAML user may not change their email',\n\t\t\t\t{\n\t\t\t\t\tuserId: currentUser.id,\n\t\t\t\t\tpayload: payloadWithoutPassword,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new BadRequestError('SAML user may not change their email');\n\t\t}\n\n\t\tif (mfaEnabled) {\n\t\t\tif (!payload.mfaCode) {\n\t\t\t\tthrow new BadRequestError('Two-factor code is required to change email');\n\t\t\t}\n\n\t\t\tconst isMfaCodeValid = await this.mfaService.validateMfa(userId, payload.mfaCode, undefined);\n\t\t\tif (!isMfaCodeValid) {\n\t\t\t\tthrow new InvalidMfaCodeError();\n\t\t\t}\n\t\t} else {\n\t\t\tif (currentUser.password === null) {\n\t\t\t\tthis.logger.debug('User with no password changed their email', {\n\t\t\t\t\tuserId: currentUser.id,\n\t\t\t\t\tpayload: payloadWithoutPassword,\n\t\t\t\t});\n\t\t\t\treturn;","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/me.controller.ts#L119-L155","documentation":"A BadRequestError (HTTP 400) from validateChangingUserEmail when isSamlLicensedAndEnabled() is true. When SAML is licensed and active, email is the immutable key that maps a user to their IdP account, so email changes are blocked. Logged at debug with the userId and payload before throwing.","triggerScenarios":"PATCH /me where the email field differs from the current email, while the instance has SAML licensed and enabled. The check is the first guard inside validateChangingUserEmail.","commonSituations":"SAML-enabled instance where a user tries to change their email; admin enables SAML after users were accustomed to self-service email changes; IdP email mismatch the user tries to fix client-side.","solutions":["Change the user's email in the SAML Identity Provider; it will sync on next login.","If SAML was enabled by mistake, disable it and restart n8n to allow email changes again.","Have an admin update the email directly in the DB only if SAML mapping is also corrected."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Block email changes when SAML is active.\nconst { samlLicensedAndEnabled } = await api.get('/sso/config');\nif (samlLicensedAndEnabled && payload.email !== me.email) {\n  throw new Error('Email is managed by SAML — change it in the IdP.');\n}","typeGuard":"function isEmailChange(p: { email?: string }, current: string): boolean {\n  return typeof p.email === 'string' && p.email.toLowerCase() !== current.toLowerCase();\n}","tryCatchPattern":"try {\n  await api.patch('/me', payload);\n} catch (e) {\n  if (e.response?.status === 400 && /SAML user may not change their email/i.test(e.response.data.message)) {\n    notify('Change your email in the SAML Identity Provider.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Disable the email field in the profile form when SAML is enabled.","Keep the IdP email as the single source of truth for SAML users.","Communicate the SAML cutover so users stop attempting email self-service."],"tags":["me","email","saml","sso","rest-api"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}