{"record":{"id":"e42eceaaea193ee2","repo":"passbolt/passbolt_api","slug":"the-user-id-is-invalid","errorCode":null,"errorMessage":"The user id is invalid.","messagePattern":"The user id is invalid\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Controller/AccountRecoveryContinue/AccountRecoveryContinueController.php","lineNumber":63,"sourceCode":"        parent::beforeFilter($event);\n    }\n\n    /**\n     * Render a page to continue the account recovery process\n     *\n     * @param string|null $userId User ID\n     * @param string|null $tokenId Token ID\n     * @param \\Passbolt\\Ee\\Service\\AccountRecoveryContinue\\AccountRecoveryContinueAggregatorService $accountRecoveryContinueService Service instance.\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if the data provided is not valid\n     */\n    public function get(\n        ?string $userId,\n        ?string $tokenId,\n        AccountRecoveryContinueAggregatorService $accountRecoveryContinueService\n    ): void {\n        if (!isset($userId) || !Validation::uuid($userId)) {\n            throw new BadRequestException(__('The user id is invalid.'));\n        }\n        if (!isset($tokenId) || !Validation::uuid($tokenId)) {\n            throw new BadRequestException(__('The authentication token id is invalid.'));\n        }\n\n        if ($this->getRequest()->is('json')) {\n            // Do not allow logged in user to recover\n            if ($this->User->role() !== Role::GUEST) {\n                throw new ForbiddenException(__('Only guests are allowed to proceed with account recovery.'));\n            }\n\n            (new AccountRecoveryRequestGetService())->getOrFail($userId, $tokenId);\n\n            $data = $accountRecoveryContinueService->get();\n\n            $this->success(__('The operation was successful.'), $data);\n        } else {\n            $this->renderHtml();","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Controller/AccountRecoveryContinue/AccountRecoveryContinueController.php#L45-L81","documentation":"BadRequestException thrown by AccountRecoveryContinueController::get() when the userId route parameter is missing or not a valid UUID. The controller validates all identifier parameters before delegating to services.","triggerScenarios":"GET request to the account recovery continue endpoint with a missing, empty, or malformed (non-UUID) user id in the URL, e.g. /account-recovery/continue/not-a-uuid/<token-id>.json","commonSituations":"Broken or hand-edited recovery link from an email template; truncated URL; client sending a username/email instead of the user UUID; old links generated before ID format changes.","solutions":["Regenerate the recovery link ensuring the full user UUID is included","Validate the user id is a UUID before making the request (Cake\\Validation::uuid())","Check the email template/link builder produces the correct route","Log the incoming URL to confirm which parameter is malformed"],"exampleFix":"// before\n$url = \"/account-recovery/continue/$userId/$tokenId.json\"; // $userId = 'admin@example.com'\n// after\n$user = $usersTable->findByUsername($email)->firstOrFail();\n$url = \"/account-recovery/continue/{$user->id}/$tokenId.json\";","handlingStrategy":"validation","validationCode":"import { uuidValidation } from 'passbolt/styleguide/lib/assertions/uuid.validation';\nif (!uuidValidation(userId)) throw new Error('user id must be a UUID');","typeGuard":"function isValidUuid(value: unknown): value is string {\n  return typeof value === 'string'\n    && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}","tryCatchPattern":"try {\n  await accountRecoveryContinueService.get(userId, tokenId);\n} catch (ApiError e) {\n  if (e.message.includes('user id is invalid')) {\n    redirectToRecoveryStart(); // regenerate a valid link\n  }\n}","preventionTips":["Always build recovery URLs from the entity's UUID field, never username/email","Validate identifiers with Validation::uuid() client-side before navigation","Escape/log full recovery URLs when debugging email links","Ensure route parameters are not truncated by URL builders"],"tags":["php","cakephp","validation","uuid"],"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"}