bitwarden/server · error · BadRequestException
Reset Password keys cannot be set to null during rotation.
Error message
Reset Password keys cannot be set to null during rotation.
What it means
Thrown by OrganizationUserRotationValidator when a rotation entry matched an org membership with a valid ResetPasswordKey (matched by OrganizationId) but the submitted ResetPasswordKey is null. Reset keys cannot be cleared via the rotation endpoint; doing so would break account recovery, so it is rejected. (A tracked TODO notes this should use IsValidResetPasswordKey once PM-31001 lands.)
Source
Thrown at src/Api/KeyManagement/Validators/OrganizationUserRotationValidator.cs:51
return result;
}
// Exclude any account recovery that do not have a key.
existing = existing.Where(o => OrganizationUser.IsValidResetPasswordKey(o.ResetPasswordKey)).ToList();
foreach (var ou in existing)
{
var organizationUser = resetPasswordKeys.FirstOrDefault(a => a.OrganizationId == ou.OrganizationId);
if (organizationUser == null)
{
throw new BadRequestException("All existing reset password keys must be included in the rotation.");
}
// Should be migrated to: if (!OrganizationUser.IsValidResetPasswordKey(organizationUser.ResetPasswordKey))
// after https://bitwarden.atlassian.net/browse/PM-31001 is resolved
if (organizationUser.ResetPasswordKey == null)
{
throw new BadRequestException("Reset Password keys cannot be set to null during rotation.");
}
ou.ResetPasswordKey = organizationUser.ResetPasswordKey;
result.Add(ou);
}
return result;
}
}
View on GitHub (pinned to e93b962371)
Solutions
- Re-encrypt the ResetPasswordKey with the new user key for every included org membership.
- To stop account recovery for an org, leave the org or have recovery disabled administratively before rotating.
- Assert every included entry has a non-null ResetPasswordKey before submitting.
Example fix
// before: trying to clear recovery
{ organizationId: o.id, resetPasswordKey: null }
// after: re-encrypt, or handle removal out of band
{ organizationId: o.id, resetPasswordKey: reencrypt(o.resetPasswordKey) } Defensive patterns
Strategy: validation
Validate before calling
const nulled = payload.resetPasswordKeys.filter(k => k.resetPasswordKey == null);
if (nulled.length) {
throw new Error(`Reset password keys cannot be null for orgs: ${nulled.map(k => k.organizationId).join(', ')}`);
} Type guard
function hasResetPasswordKey(k: { resetPasswordKey?: string | null }): boolean {
return k.resetPasswordKey != null && k.resetPasswordKey.length > 0;
} Try / catch
try {
await api.rotateKey(payload);
} catch (e) {
if (e.status === 400 && /cannot be set to null/i.test(e.message)) {
payload.resetPasswordKeys = payload.resetPasswordKeys.map(k => ({ ...k, resetPasswordKey: reencrypt(k.resetPasswordKey ?? oldKeyFor(k.organizationId)) }));
return api.rotateKey(payload);
}
throw e;
} Prevention
- Never null a reset key to disable recovery; leave the org or have an admin disable it.
- Assert every included entry has a non-null ResetPasswordKey before submitting.
- Confirm re-encryption succeeded for each org membership.
When it happens
Trigger: The reset-password-keys array includes the OrganizationId but the ResetPasswordKey field is null or was omitted during request construction.
Common situations: Client attempted to disable account recovery by nulling the key instead of leaving the org or having an admin disable recovery; serialization dropped the field; re-encryption of that key failed silently.
Related errors
- All existing reset password keys must be included in the rot
- Rotated encryption keys must be provided for all devices tha
- Emergency access keys cannot be set to null during rotation.
- WebAuthn prf keys must have user-key during rotation.
- WebAuthn prf keys must have public-key during rotation.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/06e5874310b7442e.
Report an issue: GitHub.