passbolt/passbolt_api · error · InvalidArgumentException

The user ID should be a valid UUID.

Error message

The user ID should be a valid UUID.

What it means

validateUserId throws InvalidArgumentException when the supplied user id is not a valid UUID. Refresh token queries are scoped by (token, user_id); a malformed user id can never match a row, so it is rejected before querying the database.

Solutions

  1. Pass the user's UUID (users.id from the database / the 'sub' claim of the access token).
  2. Validate with a UUID regex before calling the API.
  3. Confirm you are not swapping the token and userId arguments to getActiveRefreshToken(string $token, string $userId).
  4. Catch InvalidArgumentException and return a client input error rather than querying.

Example fix

// before
$service->getActiveRefreshToken($token, $user['username']); // email, not UUID
// after
if (!Validation::uuid($userId)) { throw new BadRequestException(); }
$service->getActiveRefreshToken($token, $userId);
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('userId must be a UUID');

Type guard

function isUuid(v: unknown): v is string {
  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 {
  $service->validateUserId($userId);
} catch (InvalidArgumentException $e) {
  throw new BadRequestException('userId must be a valid UUID', 400, $e);
}

Prevention

When it happens

Trigger: Calling queryRefreshTokenWithUserId or getActiveRefreshToken with a null, empty, or malformed userId string (e.g. an email address, an integer id, or a truncated UUID) during logout or token renewal flows.

Common situations: Passing the username/email instead of the user UUID; using the token id where the user id is expected; reading the wrong field off the authenticated session payload; string truncation when serializing ids.

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/b7e5f7e0fd7747da. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/JwtAuthentication/src/Service/RefreshToken/RefreshTokenAbstractService.php:138

     * @return void
     * @throws \InvalidArgumentException If the token is not a valid UUID
     */
    public function validateRefreshToken(mixed $token): void
    {
        if (!Validation::uuid($token)) {
            throw new InvalidArgumentException(__('The refresh token should be a valid UUID.'));
        }
    }

    /**
     * @param mixed $userId User id to be validated.
     * @return void
     * @throws \InvalidArgumentException if the $id is not valid
     */
    public function validateUserId(mixed $userId): void
    {
        if (!Validation::uuid($userId)) {
            throw new InvalidArgumentException(__('The user ID should be a valid UUID.'));
        }
    }

    /**
     * @param string|null $token Refresh token
     * @return \Cake\ORM\Query\SelectQuery
     * @throws \InvalidArgumentException If the token is not a valid UUID
     */
    public function queryRefreshToken(?string $token): SelectQuery
    {
        $this->validateRefreshToken($token);

        return $this->AuthenticationTokens->find()->where([
            'token' => $token,
            'type' => AuthenticationToken::TYPE_REFRESH_TOKEN,
        ]);
    }

View on GitHub (pinned to 31c1bbc10f)