passbolt/passbolt_api · error · BadRequestException
The email can not be changed
Error message
The email can not be changed
What it means
In a SCIM PATCH `add` operation on a user, an operation targeting the `emails` attribute is unconditionally rejected: passbolt does not allow email addresses to be modified through SCIM because the email is the user's identity/login key. It throws a 400 BadRequestException with scimType `mutability`.
Solutions
- Remove the `emails` attribute from the IdP's SCIM attribute mapping so it is never sent in PATCH operations.
- Change the email through the passbolt admin UI or the `passbolt users` CLI command instead of SCIM.
- If the address must change, delete and re-create (re-provision) the user via SCIM.
- Configure the IdP to treat email as immutable for this provisioning app.
Example fix
// before (IdP mapping sends email updates)
{"Operations":[{"op":"add","path":"emails","value":[{"value":"new@mail.com"}]}]}
// after (map emails read-only; change it server-side instead)
// passbolt: bin/cake passbolt users change_user_email <user-id> new@mail.com Defensive patterns
Strategy: validation
Validate before calling
if (String(op.path || '').startsWith('emails')) throw new Error('passbolt: emails cannot be changed via SCIM; use admin UI/CLI'); Try / catch
try { await scim.patchUser(id, ops); } catch (e) { if (e.status === 400 && e.scimType === 'mutability' && /email/i.test(e.message)) { ops = ops.filter(o => !String(o.path||'').startsWith('emails')); } else throw e; } Prevention
- Set emails mapping to read-only / DoNotSync in the IdP
- Never include emails in PATCH payloads for passbolt
- Change emails via passbolt admin UI or CLI only
When it happens
Trigger: PATCH /scim/v2/Users/<id> with op `add` and path/value containing `emails` (e.g. {"op":"add","path":"emails","value":[{"value":"new@mail.com"}]}).
Common situations: An IdP synchronization changes a user's email address and tries to propagate the change via SCIM; an admin tries to fix a typo'd email through SCIM instead of the passbolt UI/CLI; Azure AD provisioning maps the mail field as an updatable attribute.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Unable to apply operation
- Invalid data to create a SCIM Operation
- Invalid data to create a SCIM PATCH REQUEST
- Invalid schema for SCIM PATCH REQUEST
- No email with type "work" was found in the
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/87d932f199c5cd5e.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Scim/src/Utility/Resource/UserScimResource.php:606
}
break;
case 'name.familyName':
if (empty($this->lastName)) {
$userPatchData['profile']['last_name'] = $attributeValue;
}
break;
case 'active':
if ($this->active === null) {
if (is_string($attributeValue)) {
$value = in_array(strtolower($attributeValue), ['true', '1']);
} else {
$value = (bool)$attributeValue;
}
$userPatchData['disabled'] = $this->getDisabledValue($value);
}
break;
case 'emails':
throw new BadRequestException(
'The email can not be changed',
scimType: ScimException::SCIM_TYPE_MUTABILITY
);
default:
// ignore attributes not used in this application
}
break;
case Operation::TYPE_REPLACE:
switch ($attributeName) {
case 'externalId':
$scimEntryPatchData['external_identifier'] = $attributeValue;
break;
case 'userName':
$scimEntryPatchData['scim_name'] = $attributeValue;
break;
case 'name.givenName':
$userPatchData['profile']['first_name'] = $attributeValue;
break;View on GitHub (pinned to 31c1bbc10f)