passbolt/passbolt_api · error · BadRequestException

Account recovery is mandatory. Please provide the mandatory…

Error message

Account recovery is mandatory. Please provide the mandatory data.

What it means

Thrown in AccountRecoverySetupCompleteService::assertRequestSanity when the organization account recovery policy is 'mandatory' but the setup complete request omits required data: the account recovery private key or the server-stored passwords. A mandatory policy requires the user to hand over the private key and account passwords for escrow.

Solutions

  1. Ensure the setup complete payload includes the account_recovery_private_key and all required password fields
  2. Update the browser extension / client to a version that supports mandatory account recovery
  3. If the policy should not be mandatory, change the organization account recovery setting to 'opt-in' or 'disabled' in admin settings
  4. Re-run the setup wizard from the start so the client collects the mandatory data

Example fix

// before
payload = { authenticationtoken: token, user_setting: '...' };
// after (mandatory policy)
payload = { ...payload, account_recovery_private_key: armoredKey, account_recovery_password: pwd };
Defensive patterns

Strategy: validation

Validate before calling

if (orgRecoveryPolicy === 'mandatory' &&
    (!payload.account_recovery_private_key || !payload.account_recovery_password)) {
  throw new Error('Mandatory recovery data missing');
}

Type guard

const hasMandatoryRecoveryData = (p) => typeof p?.account_recovery_private_key === 'string' && p.account_recovery_private_key.length > 0 && typeof p?.account_recovery_password === 'string';

Try / catch

try {
  await setupComplete(payload);
} catch (e) {
  if (e.code === 400 && /mandatory/.test(e.message)) {
    await collectMandatoryRecoveryData();
    await setupComplete(buildPayloadWithRecoveryData());
  } else { throw e; }
}

Prevention

When it happens

Trigger: POST /setup/setup/complete under a mandatory account recovery policy where the payload lacks account_recovery_private_key or the required password fields.

Common situations: Client (extension version mismatch or custom integration) not implementing the mandatory recovery fields; user bypassing the 'download mandatory data' step; policy changed to mandatory while an old client flow is mid-setup; API scripting/tests against a mandatory-policy instance without the fields.

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/ef61546229d343a3. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/AccountRecovery/src/Service/Setup/AccountRecoverySetupCompleteService.php:134

    }

    /**
     * Assert that there is not too much or not enough data
     * Mandatory: both private key and password must be provided
     * Disabled: none of them must be provided
     *
     * @return void
     * @throws \Cake\Http\Exception\BadRequestException if data is missing or too much data is sent
     */
    protected function assertRequestSanity(): void
    {
        if ($this->policy->isDisabled()) {
            if ($this->isAccountRecoveryUserSettingProvided()) {
                throw new BadRequestException(__('Account recovery is disabled. Key backup is not supported.'));
            }
        } elseif ($this->policy->isMandatory()) {
            if (!$this->isPrivateKeyProvided() || !$this->arePasswordsProvided()) {
                throw new BadRequestException(
                    __('Account recovery is mandatory. Please provide the mandatory data.')
                );
            }
        }
    }

    /**
     * @return bool true if the account_recovery_user_setting data is set
     */
    protected function isAccountRecoveryUserSettingProvided(): bool
    {
        return is_array($this->request->getData('account_recovery_user_setting'));
    }

    /**
     * @return bool true if the account_recovery_user_setting.account_recovery_private_key data is set
     */
    protected function isPrivateKeyProvided(): bool

View on GitHub (pinned to 31c1bbc10f)