passbolt/passbolt_api · warning · BadRequestException

The user identifier should be a UUID.

Error message

The user identifier should be a UUID.

What it means

A BadRequestException thrown by UserMetadataKeysDeleteService::delete when the provided $userId is not a valid UUID. This public service method is the entry point for removing a user's metadata private keys and session keys; it validates the identifier format before touching the database.

Solutions

  1. Pass the user's actual UUID (as found in the users table / GET /users.json response)
  2. Validate the identifier client-side with a UUID check (CakePHP Validation::uuid or a regex) before calling delete
  3. Fix the caller/route so the correct path segment is used as the user ID

Example fix

// before
$service->delete($user['username']);
// after
if (!Validation::uuid($userId)) {
    throw new BadRequestException(__('The user identifier should be a UUID.'));
}
$service->delete($userId);
Defensive patterns

Strategy: validation

Validate before calling

use Cake\Validation\Validation;
if (!Validation::uuid($userId)) {
    throw new \InvalidArgumentException('userId must be a UUID');
}
$service->delete($userId);

Type guard

function isValidUuid(?string $id): bool {
    return is_string($id) && (bool) preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $id);
}

Try / catch

try {
    $service->delete($userId);
} catch (BadRequestException $e) {
    // userId was not a UUID: fix the identifier source
}

Prevention

When it happens

Trigger: Calling the user metadata keys delete service/endpoint with a malformed user identifier — empty string, numeric ID, slug, or truncated UUID instead of a 36-char UUID.

Common situations: Client code passing a username or non-UUID identifier; copy-paste errors of user IDs; routing bugs where the wrong URL segment is bound to the userId parameter; scripted cleanups iterating over non-UUID keys.

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


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/01b8e86cd0546b01. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/Metadata/src/Service/UserMetadataKeysDeleteService.php:38

use Cake\Http\Exception\InternalErrorException;
use Cake\ORM\Locator\LocatorAwareTrait;
use Cake\Utility\Hash;
use Cake\Validation\Validation;

class UserMetadataKeysDeleteService
{
    use LocatorAwareTrait;

    /**
     * Delete user metadata private & session keys.
     *
     * @param string $userId User identifier.
     * @return void
     */
    public function delete(string $userId): void
    {
        if (!Validation::uuid($userId)) {
            throw new BadRequestException(__('The user identifier should be a UUID.'));
        }

        $this->deleteMetadataPrivateKeys($userId);
        $this->deleteMetadataSessionKeys($userId);
    }

    /**
     * @param string $userId User identifier.
     * @return void
     * @throws \Cake\Http\Exception\InternalErrorException If data is not deleted.
     */
    private function deleteMetadataPrivateKeys(string $userId): void
    {
        /** @var \Passbolt\Metadata\Model\Table\MetadataPrivateKeysTable $metadataPrivateKeysTable */
        $metadataPrivateKeysTable = $this->fetchTable('Passbolt/Metadata.MetadataPrivateKeys');

        $metadataPrivateKeys = $metadataPrivateKeysTable
            ->unhydratedFind()

View on GitHub (pinned to 31c1bbc10f)