passbolt/passbolt_api · error · BadRequestException

Please provide a valid request id.

Error message

Please provide a valid request id.

What it means

Thrown by the account recovery request view endpoint when the `id` route parameter is not a valid UUID. The access-control check succeeds but the controller rejects the identifier before building the query, so this is purely an input-format error.

Solutions

  1. Ensure the id comes from the recovery requests index response (UUID format).
  2. Add a client-side UUID check before calling the endpoint.
  3. Check for string interpolation bugs producing empty ids.
  4. Verify you are not passing a response-id or user-id instead of the request id.

Example fix

// before
get(`/account-recovery/requests/${row.number}`);
// after
get(`/account-recovery/requests/${row.id}`); // row.id is a UUID
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 (!id || !UUID_RE.test(id)) throw new Error('request id must be a UUID');

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.viewAccountRecoveryRequest(id, {contain:['creator']}); } catch (e) { if (e.code === 400 && /valid request id/.test(e.message)) { /* fix id source */ } else { throw e; } }

Prevention

When it happens

Trigger: GET /account-recovery/requests/<id> with a non-UUID id (empty string, numeric id, slug, or truncated UUID).

Common situations: Admin tools listing recovery requests with a wrong column; passing an internal integer id from a legacy system; URL templates losing the id segment.

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

Appendix: source

Thrown at plugins/PassboltEe/AccountRecovery/src/Controller/AccountRecoveryRequests/AccountRecoveryRequestsViewController.php:45

{
    /**
     * List the details of one account recovery request
     *
     * @param string $id uuid of the request
     * @param \Passbolt\Rbacs\Service\ActionAccessControl\RoleActionAccessControlServiceInterface $accessControlService service assessing if the user's role has access to this action
     * @throws \Cake\Http\Exception\ForbiddenException if the user is not an admin
     * @throws \Cake\Http\Exception\NotFoundException if request id could not be found
     * @throws \Cake\Http\Exception\BadRequestException if the id is not a uuid
     * @return void
     */
    public function view(string $id, RoleActionAccessControlServiceInterface $accessControlService): void
    {
        $accessControlService->controlUserRoleActionAccess(
            $this->User->getRoleEntity(),
            UserAction::getInstance()->getActionId()
        );
        if (!Validation::uuid($id)) {
            throw new BadRequestException(__('Please provide a valid request id.'));
        }

        // Whitelisted filters and contain parameters
        $options = $this->QueryString->get([
            'contain' => [
                'armored_key', 'account_recovery_private_key_passwords',
                'account_recovery_request_responses',
                'creator',
            ],
        ]);

        $options['id'] = $id;

        /** @var \Passbolt\AccountRecovery\Model\Table\AccountRecoveryRequestsTable $accountRecoveryRequestsTable */
        $accountRecoveryRequestsTable = $this->fetchTable('Passbolt/AccountRecovery.AccountRecoveryRequests');
        $request = $accountRecoveryRequestsTable->findView($options)->firstOrFail();

        $this->success(__('The operation was successful.'), $request);

View on GitHub (pinned to 31c1bbc10f)