passbolt/passbolt_api · error · Cake\Http\Exception\InternalErrorException
Invalid UserControl user id.
Error message
Invalid UserControl user id.
What it means
UserAccessControl::__construct() validates its optional $userId argument with Cake's Validation::uuid(). If a userId is provided but is not a valid UUID string, it throws InternalErrorException('Invalid UserControl user id.'), since access-control context must be anchored to a valid user identifier.
Solutions
- Validate/normalize the id with Validation::uuid($userId) before constructing UserAccessControl, and reject invalid requests earlier (400).
- Ensure the value passed really is the user UUID, not a numeric/legacy id — fetch the UUID from the users table if needed.
- Return a proper client error instead of surfacing the internal 500: validate input at the controller layer before building the access control object.
Example fix
// before
$uac = new UserAccessControl($roleName, $this->request->getQuery('user_id')); // 500 if invalid
// after
$userId = $this->request->getQuery('user_id');
if ($userId !== null && !Validation::uuid($userId)) {
throw new BadRequestException('Invalid user id.');
}
$uac = new UserAccessControl($roleName, $userId); Defensive patterns
Strategy: validation
Validate before calling
if ($userId !== null && !\Cake\Validation\Validation::uuid($userId)) {
throw new BadRequestException('A valid user id (UUID) is required.');
}
$uac = new UserAccessControl($roleName, $userId); Type guard
function isValidUserId(?string $userId): bool {
return $userId === null || \Cake\Validation\Validation::uuid($userId);
} Try / catch
try {
$uac = new UserAccessControl($roleName, $userId);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
if (str_contains($e->getMessage(), 'Invalid UserControl user id')) {
throw new BadRequestException('Invalid user id supplied.');
}
throw $e;
} Prevention
- Validate route/query UUID parameters in controllers before passing them downstream.
- Never pass numeric legacy ids where a UUID is expected.
- Use Cake's uuid validation rule at the form/request boundary consistently.
When it happens
Trigger: Constructing `new UserAccessControl($roleName, $userId)` where $userId is a non-UUID string (e.g. an integer id, garbage, or a concatenated value) — commonly when the id comes from an unvalidated request parameter or a legacy column.
Common situations: Passing route/query parameters straight into UserAccessControl without prior UUID validation; tests using fake ids like '1' or 'test'; refactored code passing username where userId was expected.
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
- " " is not a valid group id for filter .
- " " is not a valid parent id for filter .
- " " is not a valid user id for filter .
- Invalid id
- Invalid user ID format.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/a054d204b81ca6e0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Utility/UserAccessControl.php:60
*/
private string $roleName;
/**
* @var string|null
*/
private ?string $username = null;
/**
* UserAccessControl constructor.
*
* @param string $roleName The role name
* @param string|null $userId the user uuid
* @param string|null $username the user email
*/
public function __construct(string $roleName, ?string $userId = null, ?string $username = null)
{
if (isset($userId) && !Validation::uuid($userId)) {
throw new InternalErrorException('Invalid UserControl user id.');
}
if (isset($username) && !EmailValidationRule::check($username)) {
throw new InternalErrorException('Invalid UserControl username.');
}
$this->userId = $userId;
$this->roleName = $roleName;
$this->username = $username;
}
/**
* Get the user id
*
* @return string|null
*/
public function getId(): ?string
{
return $this->userId;
}View on GitHub (pinned to 31c1bbc10f)