passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException
The account recovery is mandatory and cannot be rejected.
Error message
The account recovery is mandatory and cannot be rejected.
What it means
Thrown by validateStatusAgainstOrganizationPolicy() when the organization recovery policy is 'mandatory' but the user attempts to set their status to 'rejected'. The organization setting takes precedence over individual choice, so rejection is a bad request.
Solutions
- Check the organization policy first and send status=approved when mandatory
- Update clients to hide the opt-out option when policy is mandatory
- If opt-out must be allowed, have an admin change the organization policy away from mandatory
Example fix
// before $service->set(['status' => 'rejected']); // after $policy = (new AccountRecoveryOrganizationPolicyGetService())->getOrFail(); $status = $policy->isMandatory() ? 'approved' : $desiredStatus; $service->set(['status' => $status]);
Defensive patterns
Strategy: validation
Validate before calling
const policy = await getOrgPolicy(); if (policy.isMandatory && desiredStatus === 'rejected') desiredStatus = 'approved';
Type guard
const allowedStatus = (policy, s) => policy.isMandatory ? (s === 'approved' ? s : null) : s;
Try / catch
try { await setSettings(data); } catch (e) { if (e.status === 400 && /mandatory/.test(e.message)) { /* force approved */ } } Prevention
- Always read the organization policy before submitting settings
- Hide opt-out UI when policy is mandatory
- Refresh policy cache on client startup
When it happens
Trigger: Saving account recovery user settings with status=rejected (or opt-out) while AccountRecoveryOrganizationPolicy is set to mandatory; a client sending a default opt-out payload without checking org policy.
Common situations: Organization admins switched policy to mandatory while users still run old clients that attempt opt-out; automated scripts copying settings between orgs with different policies.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Account recovery case must be a string.
- Account recovery is disabled.
- Account recovery is disabled. Key backup is not supported.
- Account recovery is mandatory. Please provide the mandatory…
- Account recovery reason not supported.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/6d1bfaa2b20604f1.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php:136
$passwords = $this->buildPasswordEntitiesFromDataOrFail();
$key->set('account_recovery_private_key_passwords', $passwords);
$setting->set('account_recovery_private_key', $key);
}
$this->validateStatusAgainstOrganizationPolicy($setting);
return $setting;
}
/**
* @param \Passbolt\AccountRecovery\Model\Entity\AccountRecoveryUserSetting $setting Setting to validate
* @return void
* @throws \Cake\Http\Exception\BadRequestException if the status is rejected but the organisation setting to mandatory
*/
protected function validateStatusAgainstOrganizationPolicy(AccountRecoveryUserSetting $setting): void
{
if ($this->organizationPolicy->isMandatory() && $setting->isRejected()) {
throw new BadRequestException(__('The account recovery is mandatory and cannot be rejected.'));
}
}
/**
* @param string $status Status
* @throws \App\Error\Exception\CustomValidationException if the settings does not validate
* @return \Passbolt\AccountRecovery\Model\Entity\AccountRecoveryUserSetting
*/
protected function validateAccountRecoveryUserSetting(string $status): AccountRecoveryUserSetting
{
try {
return $this->AccountRecoveryUserSettings->buildAndValidateEntity($this->uac, $status);
} catch (ValidationException $exception) {
throw new CustomValidationException($exception->getMessage(), [
'account_recovery_user_setting' => $exception->getErrors(),
]);
}
}View on GitHub (pinned to 31c1bbc10f)