{"record":{"id":"721d392814961855","repo":"crowdsecurity/crowdsec","slug":"latest-decision-id-w","errorCode":null,"errorMessage":"latest decision id: %w","messagePattern":"latest decision id: %w","errorType":"exception","errorClass":"QueryFail","httpStatus":null,"severity":"error","filePath":"pkg/database/decisions.go","lineNumber":69,"sourceCode":"\t\treturn []*ent.Decision{}, fmt.Errorf(\"get all decisions with filters: %w\", QueryFail)\n\t}\n\n\treturn data, nil\n}\n\nfunc (c *Client) LatestDecisionID(ctx context.Context) (int, error) {\n\tlatest, err := c.Ent.Decision.Query().\n\t\tSelect(decision.FieldID).\n\t\tOrder(ent.Desc(decision.FieldID)).\n\t\tFirst(ctx)\n\tif err != nil {\n\t\tif ent.IsNotFound(err) {\n\t\t\treturn 0, nil\n\t\t}\n\n\t\tc.Log.Warningf(\"LatestDecisionID : %s\", err)\n\n\t\treturn 0, fmt.Errorf(\"latest decision id: %w\", QueryFail)\n\t}\n\n\treturn latest.ID, nil\n}\n\nfunc (c *Client) QueryExpiredDecisionsWithFilters(ctx context.Context, now time.Time, filter map[string][]string) ([]*ent.Decision, error) {\n\tquery := c.Ent.Decision.Query().\n\t\tSelect(decision.FieldID, decision.FieldUntil, decision.FieldScenario, decision.FieldScope, decision.FieldValue, decision.FieldType, decision.FieldOrigin, decision.FieldUUID).\n\t\tWhere(\n\t\t\tdecision.UntilLT(now),\n\t\t)\n\t// Allow a bouncer to ask for non-deduplicated results\n\tif v, ok := filter[\"dedup\"]; !ok || v[0] != \"false\" {\n\t\tquery = query.Where(longestDecisionForScopeTypeValue)\n\t}\n\n\tquery, err := applyDecisionFilter(query, filter)\n\tif err != nil {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/decisions.go#L51-L87","documentation":"Returned by Client.LatestDecisionID when the query fetching the max decision ID fails (a genuine 'not found' yields 0,nil instead). It wraps the QueryFail sentinel (\"unable to query\"); the driver error is logged as 'LatestDecisionID : <err>'.","triggerScenarios":"The last-ID SELECT fails due to DB unavailability — connection refused/timeout to MySQL/PostgreSQL, SQLite lock, missing decisions table, or driver error. Called by StreamDecision (stream pulling) and TestLatestDecisionID.","commonSituations":"LAPI starts before the database container is ready (docker-compose ordering), so every stream request fails with this until DB is up; SQLite file on a read-only mount after restore.","solutions":["Check LAPI logs for the 'LatestDecisionID :' warning to identify the driver error","If LAPI starts before the DB, add a healthcheck/startup dependency (docker-compose depends_on: condition: service_healthy)","Verify DB connectivity with the credentials in crowdsec's db config (`cscli db status` equivalent / direct client connect)","Restore write permissions on the SQLite file/mount if it is read-only"],"exampleFix":"// docker-compose before\nservices:\n  crowdsec:\n    image: crowdsecurity/crowdsec\n// after\nservices:\n  db:\n    image: mariadb\n    healthcheck: {test: [\"CMD\", \"healthcheck.sh\"], interval: 5s}\n  crowdsec:\n    image: crowdsecurity/crowdsec\n    depends_on:\n      db: {condition: service_healthy}","handlingStrategy":"try-catch","validationCode":"// before polling, verify DB reachability\nif err := sqlDB.Ping(); err != nil { log.Fatalf(\"database unreachable: %v\", err) }","typeGuard":null,"tryCatchPattern":"id, err := client.LatestDecisionID(ctx)\nif err != nil {\n    // sentinel wraps 'unable to query'; inspect LAPI log 'LatestDecisionID :'\n    log.Warnf(\"latest decision id unavailable, falling back to full pull: %v\", err)\n    id = 0 // forces full stream sync\n}","preventionTips":["Add a DB startup dependency/healthcheck so LAPI never starts before the DB","Treat 0,nil (not found) and this error differently — only the error means a real DB problem","Use the stream client's built-in retry instead of polling on failure"],"tags":["database","crowdsec","lapi","stream"],"backgroundTag":"database-query-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}