passbolt/passbolt_api · error · InvalidArgumentException
The refresh token should be a valid UUID.
Error message
The refresh token should be a valid UUID.
What it means
validateRefreshToken rejects any refresh token that is not a valid UUID via CakePHP's Validation::uuid(), throwing InvalidArgumentException before any database lookup. Passbolt refresh tokens are AuthenticationToken entities keyed by UUID, so a non-UUID can never match and is rejected early as invalid input.
Solutions
- Send the refresh token exactly as issued: a UUID string (e.g. returned by the refresh/login endpoints).
- Validate the token client-side with a UUID regex /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i before calling the API.
- Check you are not sending the access token in the refresh-token field of the request body.
- Wrap calls in a try/catch for InvalidArgumentException and surface a 400-style input error instead of proceeding.
Example fix
// before
await service.getUserIdFromToken(accessToken); // JWT, not a UUID
// after
if (!/^\h{8}-\h{4}-\h{4}-\h{4}-\h{12}$/i.test(refreshToken)) throw new Error('refresh token must be a UUID');
await service.getUserIdFromToken(refreshToken); 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(refreshToken ?? '')) throw new Error('refresh token 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->validateRefreshToken($token);
} catch (InvalidArgumentException $e) {
throw new BadRequestException('refresh_token must be a valid UUID', 400, $e);
} Prevention
- Send the UUID refresh token, never the JWT access token, in the refresh_token field
- Validate UUID format client-side before network calls
- Trim/unescape tokens copied from storage or logs
When it happens
Trigger: Calling queryRefreshToken or getUserIdFromToken (or the refresh/logout endpoints) with a null, empty, truncated, or otherwise malformed token string (e.g. 'abc123', a JWT access token mistakenly sent as the refresh token, or a base64 string).
Common situations: Confusing the JWT access token (long dot-separated string) with the UUID refresh token; sending the raw cookie value instead of the token id; copying a token with truncation or extra quoting; old clients from before refresh tokens were UUIDs.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid user ID format.
- Invalid verify token format.
- The resource identifier should be a valid UUID.
- The user id is missing or invalid.
- " " is not a valid group id for filter .
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/df598cc35bfa4d51.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/JwtAuthentication/src/Service/RefreshToken/RefreshTokenAbstractService.php:126
// Reflect the persisted state on the returned entity so callers do not operate on stale data
$refreshToken->set('active', false);
$refreshToken->set('modified', $modified);
$refreshToken->setDirty('active', false);
$refreshToken->setDirty('modified', false);
return $refreshToken;
}
/**
* @param mixed $token Refresh token to be validated.
* @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\SelectQueryView on GitHub (pinned to 31c1bbc10f)