{"record":{"id":"6d1bfaa2b20604f1","repo":"passbolt/passbolt_api","slug":"the-account-recovery-is-mandatory-and-cannot-be-rejected","errorCode":null,"errorMessage":"The account recovery is mandatory and cannot be rejected.","messagePattern":"The account recovery is mandatory and cannot be rejected\\.","errorType":"http","errorClass":"Cake\\Http\\Exception\\BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php","lineNumber":136,"sourceCode":"            $passwords = $this->buildPasswordEntitiesFromDataOrFail();\n            $key->set('account_recovery_private_key_passwords', $passwords);\n            $setting->set('account_recovery_private_key', $key);\n        }\n\n        $this->validateStatusAgainstOrganizationPolicy($setting);\n\n        return $setting;\n    }\n\n    /**\n     * @param \\Passbolt\\AccountRecovery\\Model\\Entity\\AccountRecoveryUserSetting $setting Setting to validate\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the status is rejected but the organisation setting to mandatory\n     */\n    protected function validateStatusAgainstOrganizationPolicy(AccountRecoveryUserSetting $setting): void\n    {\n        if ($this->organizationPolicy->isMandatory() && $setting->isRejected()) {\n            throw new BadRequestException(__('The account recovery is mandatory and cannot be rejected.'));\n        }\n    }\n\n    /**\n     * @param string $status Status\n     * @throws \\App\\Error\\Exception\\CustomValidationException if the settings does not validate\n     * @return \\Passbolt\\AccountRecovery\\Model\\Entity\\AccountRecoveryUserSetting\n     */\n    protected function validateAccountRecoveryUserSetting(string $status): AccountRecoveryUserSetting\n    {\n        try {\n            return $this->AccountRecoveryUserSettings->buildAndValidateEntity($this->uac, $status);\n        } catch (ValidationException $exception) {\n            throw new CustomValidationException($exception->getMessage(), [\n                'account_recovery_user_setting' => $exception->getErrors(),\n            ]);\n        }\n    }","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php#L118-L154","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n$service->set(['status' => 'rejected']);\n// after\n$policy = (new AccountRecoveryOrganizationPolicyGetService())->getOrFail();\n$status = $policy->isMandatory() ? 'approved' : $desiredStatus;\n$service->set(['status' => $status]);","handlingStrategy":"validation","validationCode":"const policy = await getOrgPolicy(); if (policy.isMandatory && desiredStatus === 'rejected') desiredStatus = 'approved';","typeGuard":"const allowedStatus = (policy, s) => policy.isMandatory ? (s === 'approved' ? s : null) : s;","tryCatchPattern":"try { await setSettings(data); } catch (e) { if (e.status === 400 && /mandatory/.test(e.message)) { /* force approved */ } }","preventionTips":["Always read the organization policy before submitting settings","Hide opt-out UI when policy is mandatory","Refresh policy cache on client startup"],"tags":["bad-request","account-recovery","policy"],"backgroundTag":"unsupported-operation","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}