passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException
Invalid request. New key or passwords are not required.
Error message
Invalid request. New key or passwords are not required.
What it means
This BadRequestException is thrown when an administrator tries to disable the account recovery organization policy while including a new organization public key or private key passwords in the request payload. Disabling recovery must be a clean operation: the current key is revoked, backups are truncated, and no replacement key material is accepted. The service rejects the request as invalid rather than silently ignoring the extra data.
Solutions
- Remove account_recovery_organization_public_key and account_recovery_private_key_passwords from the request payload when setting policy to 'disabled'.
- Send only the policy field: {"policy": "disabled"} (plus any required revocation fields handled elsewhere).
- If a client UI/library adds these fields automatically, update it or its serializer to strip key data on disable.
- Review the API docs for the disable flow: keys are revoked server-side, replacement data is never accepted.
Example fix
// before (disable with leftover key data)
await passbolt.updateAccountRecoveryOrganizationPolicy({
policy: 'disabled',
account_recovery_organization_public_key: armoredKey
});
// after (disable with minimal payload)
await passbolt.updateAccountRecoveryOrganizationPolicy({
policy: 'disabled'
}); Defensive patterns
Strategy: validation
Validate before calling
const isDisabling = payload.policy === 'disabled';
if (isDisabling && (payload.account_recovery_organization_public_key || payload.account_recovery_private_key_passwords)) {
throw new Error('Do not send new key or passwords when disabling account recovery.');
} Type guard
function isDisablePayload(p) {
return p.policy === 'disabled' &&
p.account_recovery_organization_public_key === undefined &&
p.account_recovery_private_key_passwords === undefined;
} Try / catch
try {
await passbolt.setAccountRecoveryOrganizationPolicy(payload);
} catch (e) {
if (e.status === 400 && /New key or passwords are not required/.test(e.message)) {
delete payload.account_recovery_organization_public_key;
delete payload.account_recovery_private_key_passwords;
return retry(payload);
}
throw e;
} Prevention
- Build the disable payload from scratch instead of mutating an enable/rotate payload.
- Strip key-related fields in a serializer whenever policy is 'disabled'.
- Check the GET organization-policies endpoint first to know the current state before composing the request.
When it happens
Trigger: POST/PUT to the account recovery organization settings endpoint with policy set to 'disabled' while the payload also contains 'account_recovery_organization_public_key' or 'account_recovery_private_key_passwords'. Occurs in AccountRecoveryOrganizationPolicySetService::set() at the isDisabling() branch.
Common situations: A client script or admin UI re-sends the previous payload (which included the public key) but changes only the policy field to 'disabled'; automation tooling that always includes the full settings object; API consumers copying the 'enable' request shape for the 'disable' call.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Could not validate public key data.
- $exception->getMessage() (dynamic, from wrapped…
- Invalid request. Keys are required for this change.
- Invalid request. No policy change.
- Invalid request. Passwords are required for this change.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/b7f5fa111a2645a1.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryOrganizationPolicies/AccountRecoveryOrganizationPolicySetService.php:81
// 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()) {
// if new key or passwords provided
if ($isNewKeyProvided || $isPrivateKeyPasswordsProvided) {
throw new BadRequestException(__('Invalid request. New key or passwords are not required.'));
}
// save new disabled policy, disable previous key and delete backups if any
return $this->disablePolicy($uac);
}
// if enabled => enabled
// e.g it's policy change like mandatory => opt-in
// and/or a possible key rotation
if (($isNewKeyProvided && !$isRevokedKeyProvided) || (!$isNewKeyProvided && $isRevokedKeyProvided)) {
throw new BadRequestException(__('Invalid request. Keys are required for this change.'));
}
// if key provided or revocation provided
$newKey = null;
$oldKey = null;
$passwords = null;
/** @psalm-suppress RedundantCondition */View on GitHub (pinned to 31c1bbc10f)