passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException
The user identifier should be a valid UUID.
Error message
The user identifier should be a valid UUID.
What it means
UserScimResource::setFromDatabase() expects the passbolt internal user identifier to be a valid UUID (it is used as a direct lookup key on the users table). CakePHP's Validation::uuid() rejects anything else and a BadRequestException is thrown before any database query, protecting against malformed identifiers.
Solutions
- Pass the passbolt users.id UUID (36-char, 8-4-4-4-12 hex) to setFromDatabase().
- If you have a SCIM id or externalId, resolve it via ScimEntries table to the internal UUID first.
- Validate the id with Cake\Util\Validation::uuid() before calling.
- Check where the id is extracted from (URL path, lookup map) for corruption.
Example fix
// before $userScimResource->setFromDatabase($scimEntry->external_identifier); // after $userScimResource->setFromDatabase($scimEntry->foreign_model_id); // internal users.id UUID
Defensive patterns
Strategy: validation
Validate before calling
use Cake\Validation\Validation;
if (!Validation::uuid($internalId)) {
throw new InvalidArgumentException('Internal user id must be a UUID, got: ' . var_export($internalId, true));
} Type guard
function isUuid(mixed $id): bool {
return is_string($id) && (bool)preg_match(
'/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $id);
} Try / catch
try {
$resource->setFromDatabase($internalId);
} catch (BadRequestException $e) {
// resolve the correct internal UUID before retrying
} Prevention
- Only pass users.id UUIDs into setFromDatabase, never SCIM externalId.
- Map externalId -> internal UUID via the scim_entries table when needed.
- Keep identifiers as strings end-to-end to avoid int coercion.
- Sanity-check id sources (URL params, DB rows) for truncation.
When it happens
Trigger: Calling setFromDatabase() with a non-UUID string (numeric DB id, SCIM externalId passed by mistake, empty string), from create/patch/put flows.
Common situations: Developer confuses SCIM externalId with passbolt's internal UUID; passes a legacy integer id; trims/loses part of the id in URL parsing; hardcoded test id.
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 SCIM setting id should be a valid UUID.
- The SCIM setting identifier should be a valid UUID.
- " " is not a valid group id for filter .
- " " is not a valid parent id for filter .
- " " is not a valid user id for filter .
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/f0fd2401e0add592.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Scim/src/Utility/Resource/UserScimResource.php:224
/**
* @param array $data
* @return void
*/
protected function validateScimUserData(array $data): void
{
$schemas = $data['schemas'] ?? [];
if (!in_array(SchemaIdentifier::CORE_USER, $schemas)) {
throw new BadRequestException('Invalid schema for SCIM User Resource');
}
}
/**
* @inheritDoc
*/
public function setFromDatabase(string $internalId): self
{
if (!Validation::uuid($internalId)) {
throw new BadRequestException(__('The user identifier should be a valid UUID.'));
}
/** @var \App\Model\Entity\User|null $userEntity */
$userEntity = $this->Users
->findForScim([$this->Users->aliasField('id') => $internalId], findDeleted: true)
->contain(['Profiles', 'ScimEntries'])
->first();
$this->userEntity = $userEntity;
if (!$this->userEntity) {
throw new ResourceNotFoundException(
sprintf('The %s resource with id `%s` was not found', $this->getType(), $internalId)
);
}
if ($this->userEntity->deleted) {
throw new ResourceNotFoundException(
sprintf('The %s resource with id `%s` is already deleted', $this->getType(), $internalId)
);
}
View on GitHub (pinned to 31c1bbc10f)