passbolt/passbolt_api · error · Cake\Http\Exception\BadRequestException
The permissions identifiers must be valid UUID.
Error message
The permissions identifiers must be valid UUID.
What it means
Symmetric to the group-manager transfer, _transferContentOwners validates that every permission id in the ownership-transfer payload for solely-owned resources/folders is a valid UUID and throws BadRequestException otherwise. It fails fast before mutating any permission records.
Solutions
- Send the permission .id values exactly as provided in the dry-run exception body (errors.resources.sole_owner / errors.folders.sole_owner permissions)
- Validate each id against a UUID regex before the request
- Map from the permissions array, not from the resource/folder object itself
- Ensure the owners array is non-empty before building the payload
Example fix
// before
const owners = resources.map(r => ({ id: r.id })); // resource id, not permission id
// after
const owners = resources.flatMap(r => r.permissions.filter(p => p.type === 15).map(p => ({ id: p.id, aco_foreign_key: p.aco_foreign_key }))); 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;
for (const o of owners) {
if (!UUID_RE.test(o.id)) throw new Error('permission id must be a UUID: ' + o.id);
} Try / catch
try { await transferOwnersAndDelete(payload); } catch (e) { if (e.status === 400 && /UUID/.test(e.message)) { payload = rebuildFromDryRun(); return transferOwnersAndDelete(payload); } throw e; } Prevention
- Use permission ids from the dry-run body's permissions arrays, not resource ids
- Validate id format client-side before each transfer call
- Distinguish permission.id from aco_foreign_key in your client models
When it happens
Trigger: Delete transfer where the owners array contains malformed ids, empty strings, or ids from the wrong model (e.g. aco_foreign_key or aro_foreign_key instead of the permission id).
Common situations: Client confusion between permission ids and resource ids when constructing the transfer; test fixtures with fake short ids; JSON copy/paste errors.
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.
- " " is not a valid group id for filter .
- " " is not a valid parent id for filter .
- " " is not a valid user id for filter .
- Cannot delete group user.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/8c93c667535645bd.
Report an issue: GitHub.
Appendix: source
Thrown at src/Controller/Users/UsersDeleteController.php:326
/**
* Transfer the content permissions which blocked the user delete
*
* @param \App\Model\Entity\User $user entity
* @throws \Cake\Http\Exception\BadRequestException if the array of manager is
* @return void
*/
protected function _transferContentOwners(User $user)
{
$owners = $this->request->getData('transfer.owners');
if (empty($owners)) {
return;
}
$permissionsIdsToUpdate = Hash::extract($owners, '{n}.id');
foreach ($permissionsIdsToUpdate as $id) {
if (!Validation::uuid($id)) {
throw new BadRequestException(__('The permissions identifiers must be valid UUID.'));
}
}
$contentIdsToUpdate = Hash::extract($owners, '{n}.aco_foreign_key');
sort($contentIdsToUpdate);
$contentIdBlockingDelete = $this->Permissions
->findSharedAcosByAroIsSoleOwner(PermissionsTable::RESOURCE_ACO, $user->id, ['checkGroupsUsers' => true])
->all()
->extract('aco_foreign_key')
->toArray();
if (Configure::read('passbolt.plugins.folders.enabled')) {
$foldersIdsBlockingDelete = $this->Permissions
->findSharedAcosByAroIsSoleOwner(PermissionsTable::FOLDER_ACO, $user->id, ['checkGroupsUsers' => true])
->all()
->extract('aco_foreign_key')
->toArray();View on GitHub (pinned to 31c1bbc10f)