passbolt/passbolt_api · error · CakeException

Filter is not valid.

Error message

Filter {0} is not valid.

What it means

Raised inside QueryStringComponent::validateFilters() (surfaced as 'Invalid filter. Filter {name} is not valid.') when a custom filter validator registered in $filterValidators exists but its callable returned a falsy value for the submitted values. The filter name is known and allowed, but the value did not satisfy the custom rule.

Solutions

  1. Read the inner message to identify which custom filter failed.
  2. Inspect the validator callable registered for that filter name and check what shape/format it expects.
  3. Send the values in the format the validator expects (e.g. array of UUIDs, valid enum strings).
  4. If the validator is wrong (too strict or mishandles scalar/array input), fix the callable to handle all legitimate input shapes.
  5. Log the received $values server-side to reproduce the failing payload.

Example fix

// before
'case-ids' => function ($values) { return is_string($values); },
// after
'case-ids' => function ($values) {
    $ids = (array)$values;
    return $ids !== [] && count(array_filter($ids, 'ctype_xdigit')) === count($ids);
},
Defensive patterns

Strategy: validation

Validate before calling

// Mirror the server validator's expectations before calling the API
function validateCaseIdsFilter(mixed $values): bool {
    $ids = is_array($values) ? $values : [$values];
    if ($ids === []) return false;
    foreach ($ids as $id) {
        if (!is_string($id) || !preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $id)) {
            return false;
        }
    }
    return true;
}
if (!validateCaseIdsFilter($filters['case-ids'])) {
    throw new InvalidArgumentException('case-ids must be a non-empty list of UUIDs');
}

Type guard

function isScalarOrUuidArray(mixed $values): bool {
    return is_scalar($values) || (is_array($values) && array_is_list($values) && $values !== []);
}

Try / catch

try {
    $result = $api->get('/items.json', ['query' => ['filter' => $filters]]);
} catch (BadRequestException $e) {
    if (preg_match('/Filter (\\S+) is not valid\\./', $e->getMessage(), $m)) {
        $logger->warning('Custom filter rejected', ['filter' => $m[1], 'values' => $filters[$m[1]] ?? null]);
        unset($filters[$m[1]]);
        $result = $api->get('/items.json', ['query' => ['filter' => $filters]]);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: A request sends ?filter[custom-key]=value where the controller registered a validator for custom-key, and call_user_func($filterValidators[$filterName], $values) returns false — e.g. a validator expecting an array of UUIDs receives a single non-UUID string, or a comma-list validator gets an empty value.

Common situations: Validators written too strictly (failing on empty arrays, null, or single values when the API sends scalars); clients sending values in the wrong shape (array vs string) for custom filters; locale/encoding issues in string validators; API version drift between client expectations and server validator rules.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Controller/Component/QueryStringComponent.php:353

                        break;
                    case 'has-tag':
                        self::validateFilterString($values, $filterName);
                        break;
                    case 'frequency':
                        self::validateFilterInteger($values, $filterName);
                        break;
                    case 'metadata_key_type':
                        self::validateFilterInList($values, $filterName, ['user_key', 'shared_key']);
                        break;
                    default:
                        // Check if custom filter validators were defined for this filter
                        if (!isset($filterValidators[$filterName])) {
                            $msg = __('No validation rule for filter {0}. Please create one.', $filterName);
                            throw new CakeException($msg);
                        }

                        if (!call_user_func($filterValidators[$filterName], $values)) {
                            throw new CakeException(__('Filter {0} is not valid.', $filterName));
                        }

                        break;
                }
            }
        }

        return true;
    }

    /**
     * Check if the filter is a valid string
     *
     * @param mixed $value to check
     * @param string $filtername for error message display
     * @throw CakeException if the filter is not valid
     * @return bool true if the filter is valid
     */

View on GitHub (pinned to 31c1bbc10f)