passbolt/passbolt_api · error · BadRequestException

The resource identifier should be a valid UUID.

Error message

The resource identifier should be a valid UUID.

What it means

Thrown by SecretsViewController::view() when the resourceId path parameter is not a valid UUID (Validation::uuid() fails). This is the first request-sanity check for GET /secrets/resource/{resourceId}, rejecting malformed identifiers as 400 Bad Request before any permission or database work.

Solutions

  1. Validate the resource id is a UUID before calling GET /secrets/resource/{id}.json
  2. Fetch resource ids from GET /resources.json rather than constructing them
  3. Check the client is not substituting the secret id or another entity's id
  4. Fix string interpolation/truncation in the URL builder

Example fix

// before
const secret = await api.get(`/secrets/resource/${resource.slug}.json`);
// after
if (!isUuid(resource.id)) throw new Error(`invalid resource id: ${resource.id}`);
const secret = await api.get(`/secrets/resource/${resource.id}.json`);
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(resourceId)) throw new Error(`invalid resource id: ${resourceId}`);

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.get(`/secrets/resource/${resourceId}.json`); }
catch (e) { if (e.response?.status === 400 && /UUID/.test(e.response?.data?.message ?? '')) { /* fix id source, do not retry blindly */ } }

Prevention

When it happens

Trigger: GET /secrets/resource/<id>.json with a non-UUID <id>: a resource name, numeric database key, URL-encoded garbage, or a truncated/typo'd id.

Common situations: Clients storing resource ids in the wrong column (e.g. slug); copy-paste losing characters; mixing up resource id with secret id; legacy code using incrementing ids.

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/d4343afa0115911e. Report an issue: GitHub.

Appendix: source

Thrown at src/Controller/Secrets/SecretsViewController.php:73

        $this->Resources = $this->fetchTable('Resources');
    }

    /**
     * Secret View action
     *
     * @param string $resourceId uuid Identifier of the resource
     * @throws \Cake\Http\Exception\BadRequestException if the resource id is not a uuid
     * @throws \Cake\Http\Exception\NotFoundException if the user has no current READ access on the resource
     * @throws \Cake\Http\Exception\NotFoundException if the user does not have a secret for the resource
     * @return void
     */
    public function view(string $resourceId)
    {
        $this->assertJson();

        // Check request sanity
        if (!Validation::uuid($resourceId)) {
            throw new BadRequestException(__('The resource identifier should be a valid UUID.'));
        }

        $uac = $this->User->getAccessControl();

        // Defence in depth: reject the read if the caller no longer has permission on the resource
        $hasAccess = $this->Resources->Permissions->hasAccess(
            PermissionsTable::RESOURCE_ACO,
            $resourceId,
            $uac->getId(),
            Permission::READ
        );
        if (!$hasAccess) {
            throw new NotFoundException(__('The secret does not exist.'));
        }

        // Retrieve the secret.
        /** @var \App\Model\Entity\Secret $secret */
        $secret = $this->Secrets->findByResourceUser($resourceId, $uac->getId())->first();

View on GitHub (pinned to 31c1bbc10f)