passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException
Invalid request. New key is required for key rotation.
Error message
Invalid request. New key is required for key rotation.
What it means
Composition guard in the account recovery organization policy set service: the request neither changes the policy nor provides the new server key required for key rotation, so the requested operation is undetermined/invalid for key rotation and is rejected.
Solutions
- Provide both the new public key and the revoked old key in the same request
- If the goal is to disable recovery entirely, set the policy to 'disabled' instead of sending a revoked key
- If no change is intended, omit both keys
Example fix
// before
await api.put('/account-recovery/organization-settings.json', { policy: 'opt-in', revoked_key: oldKey });
// after
await api.put('/account-recovery/organization-settings.json', { policy: 'opt-in', new_key: newPublicKey, revoked_key: oldKey }); Defensive patterns
Strategy: validation
Validate before calling
if (revokedKey && !newKey && currentPolicy === desiredPolicy) throw new Error('rotation requires a new key'); Try / catch
try { await updateSettings(payload); } catch (e) { if (e.message.includes('New key is required')) promptForNewKey(); else throw e; } Prevention
- Never send a revoked key alone
- If disabling, send policy 'disabled' instead
- Clarify revoke-vs-rotate semantics in the UI
When it happens
Trigger: PUT with unchanged policy and only the revoked key payload — client intends to revoke but forgot to attach the new organization public key.
Common situations: Confusion between 'revoke' and 'rotate' semantics; UI bug dropping the new-key field; admin thinks revoking alone is valid while the policy stays enabled.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid request. Revoked key is required for key rotation.
- An authentication token should be provided.
- Invalid request. Keys are required for this change.
- Invalid request. Passwords are required for this change.
- Account recovery case must be a string.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/94d887b7f2e1888b.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryOrganizationPolicies/AccountRecoveryOrganizationPolicySetService.php:60
// assert policy is provided as it should in any case
$newPolicy = $this->buildAndValidatePolicyEntityFromData($uac);
// Check request composition to understand user goal
$isPolicyChange = $this->isPolicyChange();
$isNewKeyProvided = $this->isPublicKeyProvided();
$isRevokedKeyProvided = $this->isRevokedKeyProvided();
$isPrivateKeyPasswordsProvided = $this->isPrivateKeyPasswordsProvided();
// if policy has not changed and (new key not provided or revoked key not provided)
if (!$isPolicyChange && !$isNewKeyProvided && !$isRevokedKeyProvided) {
throw new BadRequestException(__('Invalid request. No policy change.'));
}
if (!$isPolicyChange && $isNewKeyProvided && !$isRevokedKeyProvided) {
throw new BadRequestException(__('Invalid request. Revoked key is required for key rotation.'));
}
/** @psalm-suppress RedundantCondition */
if (!$isPolicyChange && !$isNewKeyProvided && $isRevokedKeyProvided) {
throw new BadRequestException(__('Invalid request. New key is required for key rotation.'));
}
// if disabled => enabled
if ($this->isEnabling()) {
// if public key is not provided
if (!$isNewKeyProvided) {
throw new BadRequestException(__('Invalid request. An organization recovery public key is required.'));
}
// if key revocation or passwords provided
if ($isRevokedKeyProvided || $isPrivateKeyPasswordsProvided) {
throw new BadRequestException(__('Invalid request. Revoked key or passwords are not required.'));
}
return $this->enablePolicy($uac, $newPolicy);
}
// if enabled => disabled
if ($this->isDisabling()) {View on GitHub (pinned to 31c1bbc10f)