crowdsecurity/crowdsec · error
while saving alert from %s: %w
Error message
while saving alert from %s: %w
What it means
SaveAlerts wraps the error returned by dbClient.UpdateCommunityBlocklist when persisting a CAPI community-blocklist alert and its decisions. The inner error comes from the database layer (constraint violations, DB unavailable, context cancelled).
Source
Thrown at pkg/apiserver/apic.go:891
decisions[outIdx] = decision
outIdx++
}
// shrink the list, those are deleted items
return decisions[:outIdx]
}
func (a *apic) SaveAlerts(ctx context.Context, alertsFromCapi []*models.Alert, addCounters map[string]map[string]int, deleteCounters map[string]map[string]int) error {
for _, alert := range alertsFromCapi {
setAlertScenario(alert, addCounters, deleteCounters)
log.Debugf("%s has %d decisions", *alert.Source.Scope, len(alert.Decisions))
if a.dbClient.Type == "sqlite" && (a.dbClient.WalMode == nil || !*a.dbClient.WalMode) {
log.Warningf("sqlite is not using WAL mode, LAPI might become unresponsive when inserting the community blocklist")
}
alertID, inserted, deleted, err := a.dbClient.UpdateCommunityBlocklist(ctx, alert)
if err != nil {
return fmt.Errorf("while saving alert from %s: %w", *alert.Source.Scope, err)
}
log.Printf("%s : added %d entries, deleted %d entries (alert:%d)", *alert.Source.Scope, inserted, deleted, alertID)
}
return nil
}
func (a *apic) ShouldForcePullBlocklist(ctx context.Context, blocklist *modelscapi.BlocklistLink) (bool, error) {
// we should force pull if the blocklist decisions are about to expire or there's no decision in the db
alertQuery := a.dbClient.Ent.Alert.Query()
alertQuery.Where(alert.SourceScopeEQ(fmt.Sprintf("%s:%s", types.ListOrigin, *blocklist.Name)))
alertQuery.Order(ent.Desc(alert.FieldCreatedAt))
alertInstance, err := alertQuery.First(ctx)
if err != nil {
if ent.IsNotFound(err) {
log.Debugf("no alert found for %s, force refresh", *blocklist.Name)View on GitHub (pinned to 909b515798)
Solutions
- Inspect the wrapped inner error to identify the DB-layer cause.
- Enable WAL mode for SQLite (`cscli db enable-wal`) and run `cscli db doctor`.
- Verify DB connectivity and that migrations ran (`cscli db migrate` / restart crowdsec).
- Increase pull timeout / check disk space if the error is a timeout or write failure.
Defensive patterns
Strategy: try-catch
Validate before calling
// verify DB is reachable before large pulls: // cscli db doctor && cscli db enable-wal
Try / catch
if err := a.SaveAlerts(ctx, alerts, addCounters, nil); err != nil {
var dbErr *ent.ConstraintError
if errors.As(err, &dbErr) { /* handle duplicate/conflict */ }
return fmt.Errorf("...: %w", err)
} Prevention
- Enable WAL mode for SQLite before enabling community blocklist pull.
- Monitor disk space on the DB volume.
- Apply DB migrations after every crowdsec upgrade.
When it happens
Trigger: PullTop or updateBlocklist saves fetched blocklist alerts; UpdateCommunityBlocklist fails, e.g. SQLite locked/corrupted, PostgreSQL down, context deadline exceeded during long CAPI pulls, or a malformed decision from CAPI violating schema.
Common situations: SQLite without WAL mode under concurrent LAPI writes, DB restart during community blocklist pull, disk full, huge community blocklist insert timing out, DB migration not applied after upgrade.
Related errors
- while checking if we should force pull blocklist %s: %w
- while saving alert from blocklist %s: %w
- loading token: %w
- saving token: %w
- blocklist URL is nil
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/9175dfbe07ea986b.
Report an issue: GitHub.