passbolt/passbolt_api · warning · Cake\Http\Exception\BadRequestException

Multiple has-access filters are not supported.

Error message

Multiple has-access filters are not supported.

What it means

BadRequestException (HTTP 400) from UsersIndexController::assertHasAccess: the `filter[has-access]` query parameter was supplied with more than one resource id. The endpoint only supports checking access against a single resource per request.

Solutions

  1. Issue one request per resource id, each with a single has-access value.
  2. Change client code to send only the first/selected resource id, or loop over ids.
  3. If bulk checks are needed, batch client-side across multiple single-id requests.

Example fix

// before
const ids = ['res-1', 'res-2'];
await api.getUsers({ filter: { 'has-access': ids } });
// after
const results = await Promise.all(ids.map(id =>
  api.getUsers({ filter: { 'has-access': [id] } })
));
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleHasAccess(filter) {
  const ids = filter?.['has-access'];
  if (Array.isArray(ids) && ids.length > 1) throw new Error('has-access accepts at most one resource id');
}

Try / catch

try { await api.getUsers({ filter: { 'has-access': ids } }); } catch (e) { if (e.code === 400 && /Multiple has-access/.test(e.message)) { return Promise.all(ids.map(id => api.getUsers({ filter: { 'has-access': [id] } }))); } throw e; }

Prevention

When it happens

Trigger: GET /users.json?filter[has-access]=<uuid1>,<uuid2> (or repeated has-access filters) — i.e. any request where the has-access filter array contains 2+ entries.

Common situations: Client code passing an array of resource ids assuming multi-resource support; UI selecting multiple resources and forwarding all ids; combining comma-joined values into the filter.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/Controller/Users/UsersIndexController.php:134

                $computedFindIndexOptions
            );
        }

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

    /**
     * @throws \Cake\Http\Exception\ForbiddenException if user doesn't have access to the resource requested by the filter
     * @throws \Cake\Http\Exception\BadRequestException if multiple has-access filters are requested
     * @param array $options from
     * @return void
     */
    public function assertHasAccess(array $options): void
    {
        if (isset($options['filter']['has-access']) && count($options['filter']['has-access'])) {
            if (count($options['filter']['has-access']) > 1) {
                throw new BadRequestException(__('Multiple has-access filters are not supported.'));
            }
            $resourceId = $options['filter']['has-access'][0];
            $service = new UserHasPermissionService();
            if (!$service->check(PermissionsTable::RESOURCE_ACO, $resourceId, $this->User->id())) {
                throw new ForbiddenException(__('This operation is not allowed for this user.'));
            }
        }
    }
}

View on GitHub (pinned to 31c1bbc10f)