passbolt/passbolt_api · error · BadRequestException
The role identifier is not valid.
Error message
The role identifier is not valid.
What it means
RolesDeleteService::delete rejects a role deletion request whose roleId is not a valid UUID string before touching the database. This guards the DELETE /roles/{id} endpoint against malformed identifiers with a fast 400 response.
Solutions
- Fetch role IDs via GET /roles and use the `id` field (UUID) in the DELETE URL.
- Validate the ID client-side with a UUID regex or the same Validation::uuid() rule before calling.
- Fix client code that passes name/slug instead of ID.
- If an ID looks wrong, re-list roles rather than guessing the identifier.
Example fix
// before DELETE /roles/admin -> 400 The role identifier is not valid // after DELETE /roles/8e07f60c-0d72-5f21-a10b-66c0ca44f2b0 -> 200
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;
if (!UUID_RE.test(roleId)) throw new Error('roleId must be a UUID before DELETE /roles/' + roleId); Type guard
function isUuid(v) {
return typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);
} Try / catch
try {
await api.deleteRole(roleId);
} catch (e) {
if (e.status === 400 && /identifier is not valid/i.test(e.message)) {
// refetch roles and correct the ID
} else throw e;
} Prevention
- Always take role IDs from the GET /roles response `id` field
- Validate UUID format before any roles/{id} call
- Never substitute role name/slug for the ID in URLs
- Beware URL encoding corrupting UUID characters
When it happens
Trigger: DELETE /roles/{roleId} where roleId is not a 36-char UUID — e.g. a role name ('admin'), an empty string, or a truncated ID passed by a client bug.
Common situations: Scripts substituting the role name instead of its ID, URL-encoding corruption dropping parts of the UUID, or API consumers reading the wrong field from a roles listing response.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid verify token format.
- The identifier should be a valid UUID.
- The identifier should be a valid UUID.
- The metadata key ID should be a valid UUID.
- The resource identifier should be a valid UUID.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/46c64530818773c6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Service/Roles/RolesDeleteService.php:60
/**
* Constructor.
*/
public function __construct()
{
$this->Roles = TableRegistry::getTableLocator()->get('Roles');
}
/**
* @param \App\Utility\UserAccessControl $uac UAC object.
* @param string $roleId Role identifier to update.
* @return void
*/
public function delete(UserAccessControl $uac, string $roleId): void
{
$uac->assertIsAdmin();
if (!Validation::uuid($roleId)) {
throw new BadRequestException(__('The role identifier is not valid.'));
}
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);
}
$role = $this->softDeleteRole($role, $uac);
$this->dispatchEvent(self::AFTER_ROLE_DELETE_SUCCESS_EVENT_NAME, [
'uac' => $uac,
'role' => $role,
]);
}
/**View on GitHub (pinned to 31c1bbc10f)