{"record":{"id":"5ab73869a1e1d680","repo":"passbolt/passbolt_api","slug":"the-user-id-is-missing-or-invalid","errorCode":null,"errorMessage":"The user id is missing or invalid.","messagePattern":"The user id is missing or invalid\\.","errorType":"exception","errorClass":"Cake\\Http\\Exception\\BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php","lineNumber":388,"sourceCode":"     */\n    public function assertServerPassphrase(mixed $passphrase): void\n    {\n        if (!is_string($passphrase)) {\n            $msg = __('The config for the server private key passphrase is invalid.');\n            throw new InternalErrorException($msg);\n        }\n    }\n\n    /**\n     * @param mixed $userId uuid\n     * @throws \\Cake\\Http\\Exception\\BadRequestException\n     * @return void\n     */\n    public function assertUserId(mixed $userId): void\n    {\n        if (!is_string($userId) || !Validation::uuid($userId)) {\n            $msg = __('The user id is missing or invalid.');\n            throw new BadRequestException($msg);\n        }\n    }\n\n    /**\n     * @param mixed $userData data\n     * @throws \\Cake\\Http\\Exception\\BadRequestException\n     * @return void\n     */\n    public function assertUserData(mixed $userData): void\n    {\n        if (\n            !isset($userData->gpgkey) ||\n            !isset($userData->gpgkey->fingerprint) ||\n            !isset($userData->gpgkey->armored_key) ||\n            !is_string($userData->gpgkey->fingerprint) ||\n            !PublicKeyValidationService::isValidFingerprint($userData->gpgkey->fingerprint) ||\n            !is_string($userData->gpgkey->armored_key)\n        ) {","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php#L370-L406","documentation":"assertUserId validates that the user_id field of the login request is a string and a valid UUID. It throws BadRequestException (400) because a malformed user_id means the client sent an invalid request body.","triggerScenarios":"POST /auth/jwt/login without a user_id field, with an empty string, an email address instead of a UUID, or a non-UUID id (e.g. numeric id from a legacy system).","commonSituations":"Custom scripts calling the JWT login endpoint with the username/email instead of the user UUID; missing form field after SDK upgrade; copying the wrong identifier from the UI.","solutions":["Send the user's UUID (from /users.json or the URL of their profile) as user_id in the request body","Ensure the field is a string, not a number or object","Replace any email/username value with the actual UUID","Validate UUID format client-side before calling the endpoint"],"exampleFix":"// before\nawait post('/auth/jwt/login', { user_id: 'ada@passbolt.com', challenge });\n// after\nawait post('/auth/jwt/login', { user_id: 'd57c10f5-939a-4e21-9c32-2e6e308a5a32', challenge });","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;\nif (!UUID_RE.test(userId)) throw new Error('user_id must be a UUID');","typeGuard":"function isUuid(v) { return 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 login({ user_id, challenge }); } catch (e) { if (/user id is missing or invalid/.test(e.message)) { user_id = await resolveUserIdFromEmail(email); } }","preventionTips":["Fetch the user's UUID from /users.json instead of guessing","Never send emails or usernames as user_id","Validate UUID format before the API call","Keep SDK helpers that resolve email -> uuid"],"tags":["validation","uuid","jwt","bad-request"],"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"}