crowdsecurity/crowdsec · error · ParseType

'%s' is not a boolean: %w: %w

Error message

'%s' is not a boolean: %w: %w

What it means

The include_capi alert filter parameter was given a value that could not be parsed as a boolean (e.g. "yes", "1x", empty). The parse error is double-wrapped; the filter string itself is at fault, not the query. This is the generic boolean-parse guard used by handleIncludeCapiFilter.

Source

Thrown at pkg/database/alertfilter.go:232

			rng, err = csnet.NewRange(value[0])
			if err != nil {
				return nil, err
			}
		case "since", "created_before", "until":
			if err := handleTimeFilters(param, value[0], &predicates); err != nil {
				return nil, err
			}
		case "decision_type":
			predicates = append(predicates, alert.HasDecisionsWith(decision.TypeEQ(value[0])))
		case "origin":
			predicates = append(predicates, alert.HasDecisionsWith(decision.OriginEQ(value[0])))
		case "include_capi": // allows to exclude one or more specific origins
			if err = handleIncludeCapiFilter(value[0], &predicates); err != nil {
				return nil, err
			}
		case "has_active_decision":
			if hasActiveDecision, err = strconv.ParseBool(value[0]); err != nil {
				return nil, fmt.Errorf("'%s' is not a boolean: %w: %w", value[0], err, ParseType)
			}

			if hasActiveDecision {
				predicates = append(predicates, alert.HasDecisionsWith(decision.UntilGTE(time.Now().UTC())))
			} else {
				predicates = append(predicates, alert.Not(alert.HasDecisions()))
			}
		case "kind":
			predicates = append(predicates, alert.KindEQ(value[0]))
		case "limit":
			continue
		case "sort":
			continue
		case "simulated":
			continue
		case "with_decisions":
			continue
		default:

View on GitHub (pinned to 909b515798)

Solutions

  1. Send a Go-parseable boolean: ?has_active_decision=true (or 1/0/t/f).
  2. Fix the integration producing the bad value to serialize booleans as true/false.
  3. Validate before sending (JSON boolean -> string 'true'/'false' conversion).
  4. Check URL encoding — an unencoded '&' or '=' can split the value.

Example fix

// before
GET /v1/alerts?has_active_decision=on
// after
GET /v1/alerts?has_active_decision=true
Defensive patterns

Strategy: validation

Validate before calling

if b, err := strconv.ParseBool(v); err != nil {
    return fmt.Errorf("has_active_decision must be boolean, got %q", v)
} else { _ = b }

Try / catch

_, err := client.Alerts.List(ctx, models.GetAlertsOpts{HasActiveDecision: &hasActive})
if err != nil {
    var apiErr *crowdsec.ApiErrorResponse
    if errors.As(err, &apiErr) { /* handle 400, correct param */ }
    return err
}

Prevention

When it happens

Trigger: LAPI request (applyAlertFilter / DeleteAlertWithFilter) with has_active_decision=<non-bool>, e.g. has_active_decision=on or has_active_decision=null.

Common situations: Automated scripts sending 'yes'/'no' or empty strings, third-party dashboards using non-Go boolean syntax, copy-pasted URLs with truncated values.

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 crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/3c37e74fd8717a4a. Report an issue: GitHub.