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
- Read the inner message to identify which custom filter failed.
- Inspect the validator callable registered for that filter name and check what shape/format it expects.
- Send the values in the format the validator expects (e.g. array of UUIDs, valid enum strings).
- If the validator is wrong (too strict or mishandles scalar/array input), fix the callable to handle all legitimate input shapes.
- 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
- Write a client-side mirror of each server custom validator and keep them in sync
- Make server validators tolerant of both scalar and single-element array input
- Test custom filters with empty, single-value, and multi-value payloads
- Log rejected values server-side to diagnose shape mismatches quickly
- Document the expected value format next to each filterValidators registration
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
- Invalid filter.
- No validation rule for filter
- " " is not a valid contain value.
- " " is not a valid datetime for filter .
- " " is not a valid group filter.
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)