passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException

The user id is missing or invalid.

Error message

The user id is missing or invalid.

What it means

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.

Solutions

  1. Send the user's UUID (from /users.json or the URL of their profile) as user_id in the request body
  2. Ensure the field is a string, not a number or object
  3. Replace any email/username value with the actual UUID
  4. Validate UUID format client-side before calling the endpoint

Example fix

// before
await post('/auth/jwt/login', { user_id: 'ada@passbolt.com', challenge });
// after
await post('/auth/jwt/login', { user_id: 'd57c10f5-939a-4e21-9c32-2e6e308a5a32', challenge });
Defensive patterns

Strategy: validation

Validate before calling

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(userId)) throw new Error('user_id must be a UUID');

Type guard

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); }

Try / catch

try { await login({ user_id, challenge }); } catch (e) { if (/user id is missing or invalid/.test(e.message)) { user_id = await resolveUserIdFromEmail(email); } }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/5ab73869a1e1d680. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php:388

     */
    public function assertServerPassphrase(mixed $passphrase): void
    {
        if (!is_string($passphrase)) {
            $msg = __('The config for the server private key passphrase is invalid.');
            throw new InternalErrorException($msg);
        }
    }

    /**
     * @param mixed $userId uuid
     * @throws \Cake\Http\Exception\BadRequestException
     * @return void
     */
    public function assertUserId(mixed $userId): void
    {
        if (!is_string($userId) || !Validation::uuid($userId)) {
            $msg = __('The user id is missing or invalid.');
            throw new BadRequestException($msg);
        }
    }

    /**
     * @param mixed $userData data
     * @throws \Cake\Http\Exception\BadRequestException
     * @return void
     */
    public function assertUserData(mixed $userData): void
    {
        if (
            !isset($userData->gpgkey) ||
            !isset($userData->gpgkey->fingerprint) ||
            !isset($userData->gpgkey->armored_key) ||
            !is_string($userData->gpgkey->fingerprint) ||
            !PublicKeyValidationService::isValidFingerprint($userData->gpgkey->fingerprint) ||
            !is_string($userData->gpgkey->armored_key)
        ) {

View on GitHub (pinned to 31c1bbc10f)