{"record":{"id":"022453acbbaac3c4","repo":"crowdsecurity/crowdsec","slug":"while-getting-alert-w","errorCode":null,"errorMessage":"while getting alert: %w","messagePattern":"while getting alert: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiserver/apic.go","lineNumber":913,"sourceCode":"\t}\n\n\treturn nil\n}\n\nfunc (a *apic) ShouldForcePullBlocklist(ctx context.Context, blocklist *modelscapi.BlocklistLink) (bool, error) {\n\t// we should force pull if the blocklist decisions are about to expire or there's no decision in the db\n\talertQuery := a.dbClient.Ent.Alert.Query()\n\talertQuery.Where(alert.SourceScopeEQ(fmt.Sprintf(\"%s:%s\", types.ListOrigin, *blocklist.Name)))\n\talertQuery.Order(ent.Desc(alert.FieldCreatedAt))\n\n\talertInstance, err := alertQuery.First(ctx)\n\tif err != nil {\n\t\tif ent.IsNotFound(err) {\n\t\t\tlog.Debugf(\"no alert found for %s, force refresh\", *blocklist.Name)\n\t\t\treturn true, nil\n\t\t}\n\n\t\treturn false, fmt.Errorf(\"while getting alert: %w\", err)\n\t}\n\n\tdecisionQuery := a.dbClient.Ent.Decision.Query()\n\tdecisionQuery.Where(decision.HasOwnerWith(alert.IDEQ(alertInstance.ID)))\n\n\tfirstDecision, err := decisionQuery.First(ctx)\n\tif err != nil {\n\t\tif ent.IsNotFound(err) {\n\t\t\tlog.Debugf(\"no decision found for %s, force refresh\", *blocklist.Name)\n\t\t\treturn true, nil\n\t\t}\n\n\t\treturn false, fmt.Errorf(\"while getting decision: %w\", err)\n\t}\n\n\tif firstDecision == nil || firstDecision.Until == nil || firstDecision.Until.Sub(time.Now().UTC()) < (a.pullInterval+15*time.Minute) {\n\t\tlog.Debugf(\"at least one decision found for %s, expire soon, force refresh\", *blocklist.Name)\n\t\treturn true, nil","sourceCodeStart":895,"sourceCodeEnd":931,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/apic.go#L895-L931","documentation":"ShouldForcePullBlocklist wraps the error from fetching the last alert for a blocklist via the ent ORM. NotFound is handled as a 'force refresh' signal; only other query errors (DB down, context cancelled, schema issue) reach this wrapper.","triggerScenarios":"updateBlocklist calls ShouldForcePullBlocklist for a subscribed blocklist; the alert query fails for reasons other than not-found, e.g. DB connection lost, context cancelled, or ent query error.","commonSituations":"PostgreSQL unreachable mid-cycle, SQLite file locked by another process, context timeout on slow DB, corrupted DB after failed migration.","solutions":["Read the wrapped DB error; test DB connectivity (`cscli db doctor`).","For SQLite, enable WAL and check for stale locks.","Ensure migrations ran after upgrade (`cscli db migrate`).","Retry the pull; transient DB errors typically resolve on next tick."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// check DB health first: cscli db doctor","typeGuard":null,"tryCatchPattern":"ok, err := a.ShouldForcePullBlocklist(ctx, blocklist)\nif err != nil {\n    if ent.IsNotFound(err) { /* treat as force-pull */ }\n    log.Warnf(\"transient db error, will retry next pull: %v\", err)\n    return\n}","preventionTips":["Keep SQLite in WAL mode to avoid lock errors.","Watch for context cancellations during shutdown-triggered pulls.","Run migrations after upgrades so ent queries match the schema."],"tags":["database","ent","query","blocklist"],"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"}