passbolt/passbolt_api · error · BadRequestException
The identifier should be a valid UUID.
Error message
The identifier should be a valid UUID.
What it means
findAllByAro() in PermissionsFindersTrait validates that the $aroForeignKey argument is a valid UUID and throws BadRequestException otherwise. All permission-finder methods built on it (findHighestByAcoAndAro, findAcosAccessesDiffBetweenGroupAndUser, findAcosByAroIsOwner) inherit this check, since a non-UUID ARO id would produce a broken or dangerous SQL comparison.
Solutions
- Ensure the aro id passed in is a valid UUID as stored in users.id/groups.id.
- Validate route/query parameters with Cake\Validation::uuid() in the controller before calling the finder.
- Fix upstream callers that build the id from untrusted input (add parameter validation).
- If ids come from an external system, map legacy integer ids to passbolt UUIDs first.
Example fix
// before
$perms = $this->Permissions->findHighestByAcoAndAro($aco, $userIdFromRequest);
// after
use Cake\Validation\Validation;
if (!Validation::uuid($userIdFromRequest)) {
throw new BadRequestException('The identifier should be a valid UUID.');
}
$perms = $this->Permissions->findHighestByAcoAndAro($aco, $userIdFromRequest); Defensive patterns
Strategy: type-guard
Validate before calling
use Cake\Validation\Validation; if (!Validation::uuid($aroForeignKey)) { throw new Cake\Http\Exception\BadRequestException('aroForeignKey must be a UUID'); } Type guard
function isUuidString(mixed $v): bool { return is_string($v) && Cake\Validation\Validation::uuid($v); } Try / catch
try { $perms = $this->Permissions->findHighestByAcoAndAro($aco, $aroId); } catch (\Cake\Http\Exception\BadRequestException $e) { // return 400: invalid identifier } Prevention
- Validate route parameters with Validation::uuid() before querying.
- Never pass slugs or integer ids where UUIDs are expected.
- Type-hint parameters as string and reject empty values early.
- Map legacy/external ids to passbolt UUIDs at integration boundaries.
When it happens
Trigger: Calling any of the permission finders (or the controller endpoints that use them, e.g. permission lookups for a resource) with a user/group id that is null-coerced to '', a slug, an integer id, or otherwise malformed instead of a 36-char UUID.
Common situations: Route parameters picked up from a mistyped URL (e.g. /permissions/user/not-a-uuid); legacy integrations sending integer ids; unvalidated user input passed straight into the query; tests using placeholder ids like '1' or 'abc'.
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
- The metadata session key identifier should be a UUID.
- The metadata session key identifier should be a UUID.
- The permissions data must be an array.
- The SSO setting id should be a uuid.
- Account recovery case must be a string.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/12d704f34d981e74.
Report an issue: GitHub.
Appendix: source
Thrown at src/Model/Traits/Permissions/PermissionsFindersTrait.php:106
/**
* Returns a query retrieving the permissions an aro have.
*
* The $checkGroupsUsers will also return the permissions inherited from the groups the aro is member of.
*
* @param string $acoType The aco type. By instance Resource or Folder.
* @param string $aroForeignKey The target aro id. By instance a user or a group id.
* @param array|null $options options
* [
* bool $checkGroupsUsers Check also for the groups the aro is member of
* ]
* @return \Cake\ORM\Query\SelectQuery
* @throws \Cake\Http\Exception\BadRequestException if the aro foreign key is not a valid UUID
*/
public function findAllByAro(string $acoType, string $aroForeignKey, ?array $options = []): SelectQuery
{
if (!Validation::uuid($aroForeignKey)) {
throw new BadRequestException(__('The identifier should be a valid UUID.'));
}
$checkGroupsUsers = Hash::get($options, 'checkGroupsUsers', false);
// Retrieve also the permissions for the groups a user is member of.
if ($checkGroupsUsers) {
$aroForeignKeys = $this->Groups->GroupsUsers->find()
->select('group_id')
->where(['user_id' => $aroForeignKey])
->epilog('UNION SELECT :aroForeignKey')
->bind(':aroForeignKey', $aroForeignKey);
} else {
$aroForeignKeys = [$aroForeignKey];
}
return $this->find()
->where([
'Permissions.aco' => $acoType,
'Permissions.aro_foreign_key IN' => $aroForeignKeys,View on GitHub (pinned to 31c1bbc10f)