passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException

Invalid request. Revoked key is required for key rotation.

Error message

Invalid request. Revoked key is required for key rotation.

What it means

When the policy value stays the same but a NEW public key is supplied, Passbolt interprets this as a key rotation, which requires also providing the revoked (old) key. Without the revoked key the old key could not be properly marked revoked, so the request is rejected.

Solutions

  1. Include the old active key as the revoked key in the same request (armored_key for revocation + new key)
  2. Follow the documented rotation payload: policy (unchanged), new public key, and revoked key together
  3. If you don't want rotation, remove the new key from the payload

Example fix

// before
await api.put('/account-recovery/organization-settings.json', { policy: 'opt-in', new_key: newPublicKey });
// after
const active = await getActiveOrgKey();
await api.put('/account-recovery/organization-settings.json', { policy: 'opt-in', new_key: newPublicKey, revoked_key: active.armored_key });
Defensive patterns

Strategy: validation

Validate before calling

if (newKey && !revokedKey && currentPolicy === desiredPolicy) throw new Error('rotation requires the old key too');

Try / catch

try { await updateSettings(payload); } catch (e) { if (e.message.includes('Revoked key is required')) attachActiveKeyAndRetry(); else throw e; }

Prevention

When it happens

Trigger: PUT with unchanged policy plus `armored_key` (new key) but without the `revoked_key`/old key payload — e.g. partial payload from a client that forgot the old key.

Common situations: UI sends only the new key field during rotation; admin tries to 'replace' the key without revoking the old one; incomplete migration scripts.

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


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/8f35c8fc0d1c34e2. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryOrganizationPolicies/AccountRecoveryOrganizationPolicySetService.php:56

    public function set(UserAccessControl $uac, array $data): AccountRecoveryOrganizationPolicy
    {
        $this->setData($data);

        // 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);

View on GitHub (pinned to 31c1bbc10f)