{"record":{"id":"19bd446efec5feaf","repo":"passbolt/passbolt_api","slug":"recovery-request-cannot-be-created-when-organization-policy","errorCode":null,"errorMessage":"Recovery request cannot be created when organization policy is disabled.","messagePattern":"Recovery request cannot be created when organization policy is disabled\\.","errorType":"http","errorClass":"Cake\\Http\\Exception\\BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryRequests/AccountRecoveryRequestCreateService.php","lineNumber":121,"sourceCode":"        }\n\n        $event = new Event(static::REQUEST_CREATED_EVENT_NAME, $request);\n        EventManager::instance()->dispatch($event);\n\n        return $request;\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if organization policy is disabled\n     * @return void\n     */\n    public function assertPolicyIsEnabled(): void\n    {\n        $service = new AccountRecoveryOrganizationPolicyGetService();\n        $policy = $service->get();\n        if ($policy->isDisabled()) {\n            $msg = __('Recovery request cannot be created when organization policy is disabled.');\n            throw new BadRequestException($msg);\n        }\n    }\n\n    /**\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if user id is not valid\n     * @return string uuid\n     */\n    public function assertUserId(): string\n    {\n        $userId = $this->getData('user_id');\n        if (!Validation::uuid($userId)) {\n            throw new BadRequestException(__('The user identifier should be a valid UUID.'));\n        }\n\n        return $userId;\n    }\n\n    /**","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryRequests/AccountRecoveryRequestCreateService.php#L103-L139","documentation":"AccountRecoveryRequestCreateService::assertPolicyIsEnabled fetches the organization account-recovery policy via AccountRecoveryOrganizationPolicyGetService and throws BadRequestException if the policy is disabled. Account recovery requests are only allowed while the organization policy is enabled ('mandatory' or 'opt-in'), so requests against a disabled policy are rejected up front.","triggerScenarios":"POST /account-recovery/requests while the organization setting account_recovery_organization_policy is 'disabled' — e.g. an admin disabled recovery after the user's client cached an enabled state, or the feature was never enabled on the instance.","commonSituations":"Admin turned the policy off while users were mid-recovery; fresh instance where account recovery was never enabled; plugin installed but organization settings still disabled; users with stale bookmarks/automation hitting the endpoint post-disable.","solutions":["Have an administrator re-enable account recovery in the organization settings (set policy to 'opt-in' or 'mandatory') before retrying","Check the current policy via GET /account-recovery/organization-policies to confirm it is disabled","Use an alternative account-recovery route (e.g. admin-assisted recovery or the recovery token from email) while the policy is disabled","Ensure the AccountRecovery plugin settings were fully saved/enabled if you expected it to be on"],"exampleFix":"// before (org policy disabled)\nPUT /account-recovery/organization-policies {\"policy\": \"disabled\"}  → POST /account-recovery/requests fails\n// after (enable first, then request)\nPUT /account-recovery/organization-policies {\"policy\": \"opt-in\"}\nPOST /account-recovery/requests {\"user_id\": \"...\", \"authentication_token\": {...}}","handlingStrategy":"try-catch","validationCode":"// Check policy state before attempting a recovery request:\n$policy = (new AccountRecoveryOrganizationPolicyGetService())->get();\nif ($policy->isDisabled()) {\n    // do not call create(); surface 'account recovery disabled' to the user instead\n}","typeGuard":"$policyIsUsable = fn($policy): bool => !$policy->isDisabled()\n    && in_array($policy->policy, ['opt-in', 'mandatory'], true);","tryCatchPattern":"try {\n    $request = $createService->create($uac, $data);\n} catch (\\Cake\\Http\\Exception\\BadRequestException $e) {\n    if (str_contains($e->getMessage(), 'organization policy is disabled')) {\n        // guide user/admin to enable the policy or use an alternative recovery path\n    }\n}","preventionTips":["Fetch GET /account-recovery/organization-policies before offering the recovery UI to users","Hide/disable the self-recovery flow in clients when the policy is disabled","Coordinate with admins: disabling the policy mid-flight breaks in-progress recoveries","On instances where recovery is expected, verify plugin settings were saved during setup"],"tags":["account-recovery","policy-disabled","feature-flag"],"backgroundTag":"feature-not-enabled","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"}