passbolt/passbolt_api · error · BadRequestException
The identifier should be a valid UUID.
Error message
The identifier should be a valid UUID.
What it means
In the bulk expiry update payload each resource entry must carry a 'id' field that is a valid UUID. validateAndParsePayload throws this BadRequestException when the id key is missing or fails CakePHP's Validation::uuid() check.
Solutions
- Supply a valid v4 UUID in each item's 'id' field
- Fetch real resource IDs from GET /resources.json first and use the 'id' field of each returned resource
- Trim whitespace and re-check for copy/paste corruption of the UUID
Example fix
// before
data: [{"id": "resource-123", "expired": "2026-01-01"}]
// after
data: [{"id": "8e3874ae-4b40-590b-968a-418f70bdbb85", "expired": "2026-01-01"}] Defensive patterns
Strategy: validation
Validate before calling
foreach ($data as $item) {
if (!isset($item['id']) || !\Cake\Validation\Validation::uuid($item['id'])) {
throw new \InvalidArgumentException("Invalid resource id: " . json_encode($item['id'] ?? null));
}
} Type guard
function isUuid(mixed $id): bool {
return is_string($id) && \Cake\Validation\Validation::uuid($id);
} Try / catch
try {
$service->updateMany($uac, $data);
} catch (BadRequestException $e) {
if ($e->getMessage() === 'The identifier should be a valid UUID.') {
// fix payload ids and retry
}
} Prevention
- Copy resource IDs from API responses, not by hand
- Validate UUIDs with Validation::uuid() before calling the service
- Store IDs as canonical lowercase UUID strings
When it happens
Trigger: Payload items with no 'id' key, an empty id, or a malformed id like '123' or 'resource-1' submitted to the resources expiry update endpoint.
Common situations: Hardcoded test IDs; reading IDs from a spreadsheet/export that truncated or reformatted them; confusing resource IDs with folder or permission 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
- The identifier should be a valid UUID.
- The SSO setting id should be a uuid.
- The SSO setting id should be a uuid.
- Invalid id
- Invalid status.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/2c9c94ffb480b6ba.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/PasswordExpiryPolicies/src/Service/Resources/PasswordExpiryPoliciesResourcesExpiryUpdateService.php:84
/**
* @param array $data payload
* @return array<string, \Cake\I18n\DateTime|null> array with the resourceIds as keys and the expiry date as value
* @throws \Cake\Http\Exception\BadRequestException if the expired value are not valid
* @throws \Cake\Http\Exception\BadRequestException if the resource_id value are not valid
* @throws \Cake\Http\Exception\BadRequestException if the resource_id value is found twice in the payload
* @throws \Cake\Http\Exception\BadRequestException if the sanitized array is empty
*/
protected function validateAndParsePayload(array $data): array
{
$dataSanitized = [];
foreach ($data as $resource) {
if (!is_array($resource)) {
throw new BadRequestException(__('An array of arrays is expected.'));
}
$resourceId = $resource['id'] ?? null;
if (!Validation::uuid($resourceId)) {
throw new BadRequestException(__('The identifier should be a valid UUID.'));
}
$isExpiredDefined = array_key_exists('expired', $resource);
if (!$isExpiredDefined) {
throw new BadRequestException(__('The expiry date is required.'));
}
$expiryDate = $resource['expired'];
if (array_key_exists($resourceId, $dataSanitized)) {
throw new BadRequestException(__('The identifier should be unique: {0}.', $resourceId));
}
$dataSanitized[$resourceId] = is_null($expiryDate) ? $expiryDate : new DateTime($expiryDate);
}
if (empty($dataSanitized)) {
throw new BadRequestException(__('The data should not be empty.'));
}
return $dataSanitized;
}
View on GitHub (pinned to 31c1bbc10f)