passbolt/passbolt_api · error · BadRequestException
Account recovery reason not supported.
Error message
Account recovery reason not supported.
What it means
Thrown by UserRecoverService::assertRecoveryCase when the 'case' field is a string but is not one of the values in ACCOUNT_RECOVERY_CASES. Only specific recovery reasons ('default', 'lost-token', etc.) are accepted; any other string is rejected with this message.
Solutions
- Check the exact allowed values in UserRecoverService::ACCOUNT_RECOVERY_CASES and send one verbatim.
- Fix typos — values are exact string matches, e.g. "lost-token" not "lost token".
- If you don't need a specific case, omit the field (defaults are applied).
- Verify your passbolt version supports the case you're sending (Pro-only or newer-release cases are rejected on older/CE servers).
Example fix
// before
{"username":"u@x.com","case":"password-reset"}
// after
{"username":"u@x.com","case":"lost-token"} Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED_CASES = ['default', 'lost-token', 'lost-passphrase', 'mfa-reset']; // per your server version's ACCOUNT_RECOVERY_CASES
if (body.case !== undefined && !ALLOWED_CASES.includes(body.case)) {
throw new Error(`Unsupported recovery case: ${body.case}`);
} Try / catch
try {
await recover(body);
} catch (e) {
if (e.response?.body?.message?.includes('reason not supported')) {
console.error(`Unknown case "${body.case}"; use one of the documented values or omit it.`);
}
} Prevention
- Copy case values verbatim from your server version's UserRecoverService::ACCOUNT_RECOVERY_CASES.
- Centralize the case strings as constants in your client instead of inlining literals.
- Pin client docs/tests to the passbolt version you deploy — case names can differ across versions and editions.
When it happens
Trigger: POST /recover.json with {"username": "u@x.com", "case": "forgot-password"} or any misspelled/unimplemented case value.
Common situations: Typos in the case value (e.g. 'lostpassword' vs 'lost-token'); API version drift where a case name was renamed or added in a newer passbolt version; docs from a different version or from the Pro edition listing cases unavailable in CE.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Account recovery case must be a string.
- Please provide a valid email address.
- Account recovery is disabled.
- An array of arrays is expected.
- An authentication token should be provided.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/4af237ade2e4a0ce.
Report an issue: GitHub.
Appendix: source
Thrown at src/Service/Users/UserRecoverService.php:140
->setLayout('default')
->setTemplate('triage');
}
/**
* @return string self::ACCOUNT_RECOVERY_CASE_DEFAULT default
*/
protected function assertRecoveryCase(): string
{
$case = $this->request->getData('case') ?? null;
if (!isset($case)) {
return self::ACCOUNT_RECOVERY_CASE_DEFAULT;
}
if (!is_string($case)) {
throw new BadRequestException(__('Account recovery case must be a string.'));
}
if (!in_array($case, self::ACCOUNT_RECOVERY_CASES)) {
throw new BadRequestException(__('Account recovery reason not supported.'));
}
return $case;
}
/**
* Assert some username data is provided
*
* @throws \Cake\Http\Exception\BadRequestException if the username is not valid
* @throws \Cake\Http\Exception\BadRequestException if the username is not provided
* @return string validated username
*/
protected function assertUsername(): string
{
$username = $this->request->getData('username') ?? null;
if (!isset($username) || !is_string($username) || !EmailValidationRule::check($username)) {
throw new BadRequestException(__('Please provide a valid email address.'));
}View on GitHub (pinned to 31c1bbc10f)