crowdsecurity/crowdsec · warning · InvalidFilter
invalid contains value: %w: %w
Error message
invalid contains value: %w: %w
What it means
applyDecisionFilter rejects the request because the 'contains' query parameter is not a valid boolean. The filter builder wraps strconv.ParseBool's error together with the sentinel InvalidFilter so API callers can identify it as a client-supplied bad filter.
Source
Thrown at pkg/database/decisionfilter.go:41
else, return bans that are *contained* by the given value (value is the outer)*/
/*the simulated filter is a bit different : if it's not present *or* set to false, specifically exclude records with simulated to true */
if v, ok := filter["simulated"]; ok {
if v[0] == "false" {
query = query.Where(decision.SimulatedEQ(false))
}
delete(filter, "simulated")
} else {
query = query.Where(decision.SimulatedEQ(false))
}
for param, value := range filter {
switch param {
case "contains":
contains, err = strconv.ParseBool(value[0])
if err != nil {
return nil, fmt.Errorf("invalid contains value: %w: %w", err, InvalidFilter)
}
case "scopes", "scope": // Swagger mentions both of them, let's just support both to make sure we don't break anything
scopes := strings.Split(value[0], ",")
for i, scope := range scopes {
switch strings.ToLower(scope) {
case "ip":
scopes[i] = types.Ip
case "range":
scopes[i] = types.Range
case "country":
scopes[i] = types.Country
case "as":
scopes[i] = types.AS
}
}
query = query.Where(decision.ScopeIn(scopes...))
case "value":View on GitHub (pinned to 909b515798)
Solutions
- Send only strconv.ParseBool-accepted values: true/false (or 1/0, t/f, TRUE/FALSE variants).
- Remove the 'contains' parameter entirely if you don't need it (defaults to false semantics).
- In client code, parse and validate the boolean before building the request.
- Check the wrapped strconv error to confirm it is a syntax error, not something else.
Example fix
// before GET /v1/decisions?contains=yes // after GET /v1/decisions?contains=true
Defensive patterns
Strategy: validation
Validate before calling
func validContains(v string) bool {
_, err := strconv.ParseBool(v)
return err == nil
}
// use: validContains(containsParam) || omit param Try / catch
resp, err := lapi.GetDecisions(ctx, models.GetDecisionsOpts{Contains: &contains})
if err != nil && strings.Contains(err.Error(), "invalid contains value") {
return fmt.Errorf("client bug: contains must be a bool, got %q", containsRaw)
} Prevention
- Only send true/false for boolean query params
- Never interpolate raw user input into query strings
- Serialize bools with a typed API client, not string concat
- Add client-side unit tests for filter serialization
When it happens
Trigger: Hitting the Local API decisions endpoints (e.g. GET /v1/decisions?contains=yes123) with a 'contains' value outside strconv.ParseBool's accepted set (1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False).
Common situations: Scripts passing 'yes'/'no', 'on'/'off', or an empty value for contains; bouncers written against an assumed API contract; URL-encoded or duplicated parameters garbling the boolean.
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
- unable to convert '%s' to int: %w: %w
- invalid limit value: %w: %w
- invalid offset value: %w: %w
- invalid id_gt value: %w: %w
- '%s' doesn't exist: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/5acc93983b1b2456.
Report an issue: GitHub.