crowdsecurity/crowdsec · error
could not delete alerts: %w
Error message
could not delete alerts: %w
What it means
The ent DELETE removing alerts below the computed max ID (total count minus maxItems) failed in FlushAlerts' max-items branch. The query keeps alerts with active decisions; the failure is at DB execution. Orphan alerts may remain on MySQL — a later flush run cleans them up, which is expected, not data loss.
Source
Thrown at pkg/database/flush.go:385
return fmt.Errorf("could not get last alert: %w", err)
}
if len(lastAlert) != 0 {
maxid := lastAlert[0].ID - maxItems
c.Log.Debugf("FlushAlerts (max id): %d", maxid)
if maxid > 0 {
// This may lead to orphan alerts (at least on MySQL), but the next time the flush job will run, they will be deleted
// Alerts that still carry an active decision are kept regardless of the count: deleting them would
// cascade-delete the live decision. They are flushed on a later run, once their decisions expire.
deletedByNbItem, err = c.Ent.Alert.Delete().Where(
alert.IDLT(maxid),
alertWithoutActiveDecision(time.Now().UTC()),
).Exec(ctx)
if err != nil {
c.Log.Errorf("FlushAlerts: Could not delete alerts: %s", err)
return fmt.Errorf("could not delete alerts: %w", err)
}
}
}
}
if deletedByNbItem > 0 {
c.Log.Infof("flushed %d/%d alerts because the max number of alerts has been reached (%d max)",
deletedByNbItem, totalAlerts, maxItems)
}
if deletedByAge > 0 {
c.Log.Infof("flushed %d/%d alerts because they were created %s ago or more",
deletedByAge, totalAlerts, maxAge)
}
return nil
}
View on GitHub (pinned to 909b515798)
Solutions
- Inspect the wrapped driver error in logs for the exact SQL failure
- Restore database connectivity/locks and let the next flush cycle retry
- If context cancellation, avoid stopping crowdsec during heavy flushes or increase flush frequency so batches stay small
- Check disk space on the DB volume — full disk fails deletes
Defensive patterns
Strategy: try-catch
Validate before calling
// check disk space / connectivity before large flush
if err := db.Ping(); err != nil { skipFlush = true } Try / catch
if err := c.FlushAlerts(ctx, since, maxItems); err != nil {
if errors.Is(err, context.Canceled) { return } // shutdown, not a fault
scheduleRetry(nextFlushInterval)
} Prevention
- Flush in smaller batches to shorten the delete transaction
- Monitor DB health before triggering flushes
- Ensure adequate disk space on the database volume
When it happens
Trigger: The `Alert.Delete().Where(alert.IDLT(maxid), alertWithoutActiveDecision(...))` ent mutation fails — DB connection loss, driver-level constraint, or ctx cancellation during the delete.
Common situations: Database restarted mid-flush; SQLite lock contention with a concurrently running LAPI write; connection pool exhausted on MySQL/Postgres.
Related errors
- alert graph delete batch decisions: %w
- alert graph delete batch: %w
- hard delete decisions with provided filter: %w
- unable to delete
- while getting allowlist %s: %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/2eeb340a1b5626bf.
Report an issue: GitHub.