crowdsecurity/crowdsec · error · QueryFail
query decision failed: %w
Error message
query decision failed: %w
What it means
Returned by Client.QueryDecisionWithFilter when its Scan of distinct decision fields (value/scope/origin) fails. Wraps QueryFail ("unable to query"); the real error is logged as 'QueryDecisionWithFilter : <err>'. Called by GetDecision (the LAPI GET /decisions handler).
Source
Thrown at pkg/database/decisions.go:152
query, err = applyDecisionFilter(query, filter)
if err != nil {
return []*ent.Decision{}, err
}
err = query.Select(
decision.FieldID,
decision.FieldUntil,
decision.FieldScenario,
decision.FieldType,
decision.FieldStartIP,
decision.FieldEndIP,
decision.FieldValue,
decision.FieldScope,
decision.FieldOrigin,
).Scan(ctx, &data)
if err != nil {
c.Log.Warningf("QueryDecisionWithFilter : %s", err)
return []*ent.Decision{}, fmt.Errorf("query decision failed: %w", QueryFail)
}
return data, nil
}
// ent translation of https://stackoverflow.com/a/28090544
func longestDecisionForScopeTypeValue(s *sql.Selector) {
t := sql.Table(decision.Table)
s.LeftJoin(t).OnP(sql.And(
sql.ColumnsEQ(
t.C(decision.FieldValue),
s.C(decision.FieldValue),
),
sql.ColumnsEQ(
t.C(decision.FieldType),
s.C(decision.FieldType),
),
sql.ColumnsEQ(View on GitHub (pinned to 909b515798)
Solutions
- Check LAPI logs for 'QueryDecisionWithFilter :' to see the driver error
- Verify DB reachability/locks; pause backups that take SQLite exclusive locks or use a server DB
- After a CrowdSec upgrade, ensure migrations completed (`cscli db migrate`)
- Have bouncers retry with backoff — this is a transient availability error, not a bad request
Example fix
// bouncer-side retry (pseudo)
// before
resp = lapi.GetDecisions()
// after
for i := 0; i < 3; i++ {
resp, err = lapi.GetDecisions()
if err == nil { break }
time.Sleep(backoff(i))
} Defensive patterns
Strategy: retry
Validate before calling
// client-side: confirm LAPI health before relying on decisions
resp, err := http.Get(lapiURL + "/health")
if err != nil || resp.StatusCode != 200 { return errors.New("LAPI unhealthy, skip decisions poll") } Try / catch
decisions, err := client.GetDecision(ctx, filter)
if err != nil {
// QueryFail sentinel: transient DB issue; back off and retry
time.Sleep(2 * time.Second)
decisions, err = client.GetDecision(ctx, filter)
} Prevention
- Implement backoff+retry in bouncers — DB hiccups are expected
- Stop SQLite backups from taking exclusive locks during bouncer polls
- Keep LAPI and DB on the same healthy host/network or use a server DB
When it happens
Trigger: DB failure during the distinct-columns scan: connection error, SQLite lock, schema mismatch, or a filter applied via applyDecisionFilter already returned OK but the raw scan hits driver issues. Caller GetDecision propagates it to LAPI clients as an HTTP 500/403 response.
Common situations: Bouncer polls /decisions during a MySQL restart or SQLite backup lock; upgraded LAPI serving decisions to an old schema DB; disk I/O errors on the DB host.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- machine not found
- decision duration '%+v': %w: %w
- get all decisions with filters: %w
- latest decision id: %w
- get expired decisions with filters: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/71a25bd528a94b6e.
Report an issue: GitHub.