passbolt/passbolt_api · error · CustomValidationException

$exception->getMessage() (dynamic, from wrapped…

Error message

$exception->getMessage() (dynamic, from wrapped ValidationException)

What it means

validateAccountRecoveryUserSetting() wraps CakePHP ValidationException raised by buildAndValidateEntity() into a CustomValidationException, propagating the original message plus errors under the 'account_recovery_user_setting' key. The message is dynamic and comes from the underlying table validation rules.

Solutions

  1. Inspect the errors object in the response (account_recovery_user_setting.*) for the failing rule
  2. Send one of the allowed status values and include all required fields
  3. Update the client to the latest API schema for account recovery settings

Example fix

// before
$service->set(['status' => 'approve']);
// after
$service->set(['status' => 'approved']);
Defensive patterns

Strategy: validation

Validate before calling

const VALID = ['approved','rejected']; if (!VALID.includes(data.status)) throw new Error('invalid status');

Type guard

const isStatus = (v) => ['approved','rejected'].includes(v);

Try / catch

try { await setSettings(data); } catch (e) { if (e.body?.account_recovery_user_setting) { showFieldErrors(e.body.account_recovery_user_setting); } }

Prevention

When it happens

Trigger: Submitting a status value that fails entity validation (invalid status enum, missing user, rule violation) via the account recovery user settings endpoint.

Common situations: Typos in the status field ('approve' vs 'approved'); payloads missing required fields; schema changes adding new validation rules not handled by older clients.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php:150

     */
    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(),
            ]);
        }
    }

    /**
     * Check that the user selected setting makes sense as per select org policy
     *
     * @param \Passbolt\AccountRecovery\Model\Entity\AccountRecoveryUserSetting $setting entity
     * @throws \Cake\Http\Exception\BadRequestException if user rejects and policy is mandatory
     * @return void
     */
    protected function assertRules(AccountRecoveryUserSetting $setting): void
    {
        if ($this->organizationPolicy->isMandatory() && !$setting->isApproved()) {
            throw new CustomValidationException(__('Invalid request. You cannot opt-out.'), [
                'account_recovery_user_setting' => [
                    'status' => [

View on GitHub (pinned to 31c1bbc10f)