passbolt/passbolt_api · error · ValidationException

Could not save the account recovery setting.

Error message

Could not save the account recovery setting.

What it means

Thrown when saving the user entity during account recovery setup completion succeeds for the user but the associated account_recovery_user_setting association fails validation. The ValidationException carries the entity errors and the AccountRecoveryUserSettings table so the client can render field-level errors.

Solutions

  1. Inspect the errors array in the 400 response body to see which field of the account recovery setting failed validation
  2. Send only supported account recovery user setting values (e.g. use the exact payload the web extension produces)
  3. Update the browser extension to the latest version so it posts current setting formats
  4. Check the AccountRecoveryUserSettings validation rules/table associations for custom modifications in your deployment

Example fix

// before
body = { account_recovery_user_setting: { status: 'ok' } }; // invalid value
// after
body = { account_recovery_user_setting: { status: 'approved' } }; // supported enum value
Defensive patterns

Strategy: try-catch

Validate before calling

const VALID_SETTINGS = ['approved', 'rejected'];
if (payload.account_recovery_user_setting &&
    !VALID_SETTINGS.includes(payload.account_recovery_user_setting.status)) {
  throw new Error('Invalid account recovery user setting');
}

Type guard

const isValidUserSetting = (s) => s != null && typeof s === 'object' && ['approved','rejected'].includes(s.status);

Try / catch

try {
  await setupComplete(payload);
} catch (e) {
  if (e.name === 'ValidationException' && e.errors?.account_recovery_user_setting) {
    showFieldErrors(e.errors.account_recovery_user_setting);
  } else { throw e; }
}

Prevention

When it happens

Trigger: POST setup complete with an invalid account_recovery_user_setting value — e.g. a preference value not in the allowed enum ('approved'/'rejected' style values), malformed association data, or rule violations on the setting entity.

Common situations: Client sends an unexpected user setting string; request crafted by custom API scripts with wrong setting shape; concurrent setting rows violating unique constraints; older extension posting deprecated setting values.

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

Appendix: source

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

        return is_array($this->request->getData(
            'account_recovery_user_setting.account_recovery_private_key.account_recovery_private_key_passwords'
        ));
    }

    /**
     * Adds post-save validation on account recovery related data, in case the saving failed.
     *
     * @param \App\Model\Entity\User $user User entity
     * @param array|null $saveOptions options
     * @return \App\Model\Entity\User
     */
    protected function saveUserEntity(User $user, ?array $saveOptions = []): User
    {
        $user = parent::saveUserEntity($user, $saveOptions);

        if ($this->isAccountRecoveryUserSettingProvided()) {
            if ($user->get('account_recovery_user_setting')->hasErrors()) {
                throw new ValidationException(
                    'Could not save the account recovery setting.',
                    $user->get('account_recovery_user_setting'),
                    $this->AccountRecoveryUserSettings
                );
            }

            if ($user->hasValue('account_recovery_private_key') && $user->get('account_recovery_private_key')->hasErrors()) { // phpcs:ignore
                throw new ValidationException(
                    'Could not save the account recovery private key.',
                    $user->get('account_recovery_private_key'),
                    $this->AccountRecoveryPrivateKeys
                );
            }
        }

        return $user;
    }
}

View on GitHub (pinned to 31c1bbc10f)