{"record":{"id":"28a94adf9bcf83e9","repo":"passbolt/passbolt_api","slug":"the-account-recovery-request-identifier-should-be-a-valid","errorCode":null,"errorMessage":"The account recovery request identifier should be a valid UUID.","messagePattern":"The account recovery request identifier should be a valid UUID\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/Setup/AccountRecoveryRecoverCompleteService.php","lineNumber":59,"sourceCode":"\n        return $token;\n    }\n\n    /**\n     * @param \\App\\Model\\Entity\\AuthenticationToken $token Token being updated\n     * @param string $requestId The request ID\n     * @return \\App\\Model\\Entity\\AuthenticationToken\n     * @throws \\Cake\\Datasource\\Exception\\RecordNotFoundException if the request was not found\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the request is not in \"approved\" status\n     */\n    protected function validateAccountRecoveryRequestId(\n        AuthenticationToken $token,\n        string $requestId\n    ): AuthenticationToken {\n        (new AccountRecoveryOrganizationPolicyGetService())->getOrFail();\n\n        if (!Validation::uuid($requestId)) {\n            throw new BadRequestException(__('The account recovery request identifier should be a valid UUID.'));\n        }\n\n        $RequestsTable = TableRegistry::getTableLocator()->get('Passbolt/AccountRecovery.AccountRecoveryRequests');\n\n        /** @var \\Passbolt\\AccountRecovery\\Model\\Entity\\AccountRecoveryRequest $request */\n        $request = $RequestsTable->find()\n            ->innerJoinWith('AuthenticationTokens', function (Query $q) {\n                return $q->where([\n                    'AuthenticationTokens.token' => $this->request->getData('authenticationtoken.token'),\n                ]);\n            })\n            ->where([\n                'AccountRecoveryRequests.id' => $requestId,\n                'AccountRecoveryRequests.user_id' => $token->user_id,\n            ])\n            ->contain('AccountRecoveryResponses', function (Query $query) {\n                return $query\n                    ->select([","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/Setup/AccountRecoveryRecoverCompleteService.php#L41-L77","documentation":"validateAccountRecoveryRequestId() validates the account recovery request id before building the authentication token: the organization policy must exist and the requestId must be a UUID, otherwise BadRequestException. Also loads the request row from AccountRecoveryRequests afterwards.","triggerScenarios":"Calling the account recovery setup/recover complete endpoint with a malformed or empty requestId (not a UUID); client sending a request id from a different source or truncated identifier.","commonSituations":"Clients storing the request id as an integer or string with whitespace; copying an id from a different flow (e.g. authentication token id instead of request id); old client versions with wrong URL construction.","solutions":["Send the exact account recovery request UUID returned when the recovery request was started","Validate the id with a UUID check client-side before calling","Ensure you are passing the request id, not a token or user id","Update the client if it builds the completion URL incorrectly"],"exampleFix":"// before\nconst requestId = response.token; // wrong id\n// after\nconst requestId = response.account_recovery_request_id;\nif (!isUuid(requestId)) throw new Error('invalid request id');","handlingStrategy":"validation","validationCode":"const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; if (!UUID_RE.test(requestId)) throw new Error('request id must be a UUID');","typeGuard":"const isUuid = (v) => typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);","tryCatchPattern":"try { await completeRecovery(requestId); } catch (e) { if (e.status === 400 && /valid UUID/.test(e.message)) { /* re-fetch request id from the start flow */ } }","preventionTips":["Use the request UUID exactly as returned by the recovery-start endpoint","Trim and lowercase ids; never coerce them to numbers","Distinguish request ids from auth token ids in client state"],"tags":["bad-request","uuid","account-recovery"],"backgroundTag":"invalid-identifier-format","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"}