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

  1. Fetch role IDs via GET /roles and use the `id` field (UUID) in the DELETE URL.
  2. Validate the ID client-side with a UUID regex or the same Validation::uuid() rule before calling.
  3. Fix client code that passes name/slug instead of ID.
  4. 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

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


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)