passbolt/passbolt_api · error · NotFoundException
The role does not exist or deleted.
Error message
The role does not exist or deleted.
What it means
RolesUpdateService::getRole throws this NotFoundException when no non-deleted role exists for the given ID (firstOrFail on the notDeleted finder raises RecordNotFoundException). It is surfaced as a 404 to the PUT /roles/{id} caller.
Solutions
- Confirm the role exists with GET /roles and use its current ID.
- If the role was soft-deleted, recreate it via POST /roles instead of updating.
- Invalidate/refetch any cached role listings in the client.
- Verify the UUID is copied correctly (no truncation or encoding issues).
Example fix
// before
PUT /roles/<deleted-role-id> -> 404 The role does not exist or deleted
// after
GET /roles # pick valid id
PUT /roles/<valid-id> {"name": "new-name"} -> 200 Defensive patterns
Strategy: try-catch
Validate before calling
const roles = await api.listRoles();
if (!roles.some(r => r.id === roleId)) {
throw new Error('Cannot update: role ' + roleId + ' does not exist');
} Type guard
function isUpdatableRole(roles, id) {
return Array.isArray(roles) && roles.some(r => r && r.id === id);
} Try / catch
try {
await api.updateRole(roleId, payload);
} catch (e) {
if (e.status === 404 && /does not exist or deleted/i.test(e.message)) {
// refetch roles; recreate the role if it was soft-deleted
} else throw e;
} Prevention
- Refetch GET /roles before updates instead of using cached IDs
- Treat 404 on update as stale-state: refresh then recreate if needed
- Validate the UUID before the call
- Synchronize role lists across admin sessions/tabs
When it happens
Trigger: PUT /roles/{uuid} where the UUID does not match any role, or matches a role already soft-deleted.
Common situations: Updating a role that was deleted in another session/tab, stale role ID from a cached list, double-submission after the first update deleted it, or a typo'd UUID.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- The role does not exist or deleted.
- The role could not be deleted.
- Could not delete the role, please try again later.
- Could not save the role, please try again later.
- Could not update the role, please try again later.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/06fe24229d7b4f51.
Report an issue: GitHub.
Appendix: source
Thrown at src/Service/Roles/RolesUpdateService.php:96
'role' => $result,
'oldName' => $oldName,
]);
return $result;
}
/**
* @param string $roleId Role identifier to get.
* @return \App\Model\Entity\Role
* @throws \Cake\Http\Exception\NotFoundException If role doesn't exist in the database
*/
private function getRole(string $roleId): Role
{
try {
/** @var \App\Model\Entity\Role $role */
$role = $this->Roles->find('notDeleted')->where(['id' => $roleId])->firstOrFail();
} catch (RecordNotFoundException $e) {
throw new NotFoundException(__('The role does not exist or deleted.'), null, $e);
}
return $role;
}
/**
* @param \App\Model\Entity\Role $role Role entity.
* @param array $data Data to patch.
* @param \App\Utility\UserAccessControl $uac User Access Control.
* @return \App\Model\Entity\Role
*/
private function patchRoleEntity(Role $role, array $data, UserAccessControl $uac): Role
{
$name = Hash::get($data, 'name', '');
$data = [
'name' => $name,
'modified_by' => $uac->getId(),View on GitHub (pinned to 31c1bbc10f)