bitwarden/server · warning · BadRequestException
You cannot change your email when using Key Connector.
Error message
You cannot change your email when using Key Connector.
What it means
Thrown as a 400 BadRequestException("You cannot change your email when using Key Connector.") from the legacy (feature-flag-off) path of POST accounts/email-token when user.UsesKeyConnector is true. Key Connector users obtain their user key from an external IdP/key source rather than from a master password, so the legacy local email-change flow (which rotates the master password and wrapped key) does not apply.
Source
Thrown at src/Api/Auth/Controllers/AccountsController.cs:134
var user = await _userService.GetUserByPrincipalAsync(User);
if (user == null)
{
throw new UnauthorizedAccessException();
}
// TODO: PM-39120 - PM30806_SelfServiceChangeEmailCommand flag cleanup, remove the flag
// check and keep only the SelfServiceChangeEmailCommand call.
if (_featureService.IsEnabled(FeatureFlagKeys.PM30806_SelfServiceChangeEmailCommand))
{
await _selfServiceChangeEmailCommand.InitiateChangeEmailAsync(
user, model.MasterPasswordHash, model.NewEmail);
return;
}
if (user.UsesKeyConnector)
{
throw new BadRequestException("You cannot change your email when using Key Connector.");
}
if (!await _userService.CheckPasswordAsync(user, model.MasterPasswordHash))
{
await Task.Delay(2000);
throw new BadRequestException("MasterPasswordHash", "Invalid password.");
}
var claimedUserValidationResult = await _userService.ValidateClaimedUserDomainAsync(user, model.NewEmail);
if (!claimedUserValidationResult.Succeeded)
{
throw new BadRequestException(claimedUserValidationResult.Errors);
}
await _userService.InitiateEmailChangeAsync(user, model.NewEmail);
}
View on GitHub (pinned to e93b962371)
Solutions
- Use the self-service change-email flow (the PM30806_SelfServiceChangeEmailCommand path) which supports Key Connector; ensure the feature flag is enabled.
- If Key Connector must stay, change the email at the IdP and have the user re-provision rather than via this endpoint.
- Update the client to a version that routes Key Connector users to the supported flow.
Example fix
// before: legacy endpoint rejects Key Connector users
await api.post('accounts/email-token', { newEmail, masterPasswordHash });
// after: use the self-service flow enabled by the feature flag
await api.post('accounts/email-token', { newEmail, masterPasswordHash }); // with flag PM30806 enabled server-side Defensive patterns
Strategy: validation
Validate before calling
function canChangeEmailLocally(user, flagOn) {
return !user.usesKeyConnector || flagOn;
} Type guard
function isKeyConnectorUser(u): boolean { return !!u && u.usesKeyConnector === true; } Prevention
- Gate the email-change UI on !usesKeyConnector or on the self-service feature flag.
- Enable PM30806_SelfServiceChangeEmailCommand for Key Connector orgs.
- For Key Connector users, change the email at the IdP and re-provision.
When it happens
Trigger: A Key Connector-enabled user (SSO with Key Connector) calls POST accounts/email-token while the PM30806_SelfServiceChangeEmailCommand flag is OFF, hitting the legacy branch that rejects Key Connector accounts.
Common situations: SSO organization with Key Connector enabled; the client is on a build that still uses the legacy email-change endpoint; feature flag not yet rolled out to the deployment.
Related errors
- Unauthorized.
- Invalid password.
- NewMasterPasswordHash and Key are required.
- An organization the user is a part of has enabled Automatic
- UserAlreadyExistsKeyConnector
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/9eb035ea4bf7a594.
Report an issue: GitHub.