crowdsecurity/crowdsec · error
unable to flush alerts older than %s: %w
Error message
unable to flush alerts older than %s: %w
What it means
The ent DELETE flushing alerts older than maxAge failed in FlushAlerts' max-age branch. The query deliberately keeps alerts that still have an active decision; the failure is at DB execution. A warning is logged alongside and the error propagates to the flush-job caller.
Source
Thrown at pkg/database/flush.go:344
if err != nil {
c.Log.Warningf("FlushAlerts (max items count): %s", err)
return fmt.Errorf("unable to get alerts count: %w", err)
}
c.Log.Debugf("FlushAlerts (Total alerts): %d", totalAlerts)
if maxAge != 0 {
now := time.Now().UTC()
// Delete alerts older than maxAge, but never one that still has an
// active decision (the cascade would take the live decision with it).
nbDeleted, err := c.Ent.Alert.Delete().Where(
alert.CreatedAtLTE(now.Add(-maxAge)),
alertWithoutActiveDecision(now),
).Exec(ctx)
if err != nil {
c.Log.Warningf("FlushAlerts (max age): %s", err)
return fmt.Errorf("unable to flush alerts older than %s: %w", maxAge, err)
}
c.Log.Debugf("FlushAlerts (deleted max age alerts): %d", nbDeleted)
deletedByAge = nbDeleted
}
if maxItems > 0 {
// We get the highest id for the alerts
// We subtract MaxItems to avoid deleting alerts that are not old enough
// This gives us the oldest alert that we want to keep
// We then delete all the alerts with an id lower than this one
// We can do this because the id is auto-increment, and the database won't reuse the same id twice
lastAlert, err := c.QueryAlertWithFilter(ctx, map[string][]string{
"sort": {"DESC"},
"limit": {"1"},
// we do not care about fetching the edges, we just want the id
"with_decisions": {"false"},
})View on GitHub (pinned to 909b515798)
Solutions
- Read the wrapped error: for lock contention on SQLite, stop concurrent cscli usage or switch to Postgres/MySQL for busy installs.
- For timeouts on large tables, run the flush when the system is quiet, or prune manually with cscli alerts delete --until.
- Check DB connectivity and server logs if the connection was dropped mid-query.
- Ensure the schema matches the binary version (restart crowdsec / run migrations) after upgrades.
- Retry — the next scheduler run in one minute will attempt the flush again.
Example fix
// manual relief when the automated flush keeps timing out on a huge table cscli alerts delete --until 2025-01-01T00:00:00Z --batch 1000 // then restart crowdsec so the scheduler resumes with a smaller backlog
Defensive patterns
Strategy: try-catch
Validate before calling
if err := c.Ent.Alert.Query().Limit(1).Exec(ctx); err != nil {
return fmt.Errorf("database unreachable, skipping flush: %w", err)
} Type guard
if c == nil || c.Ent == nil {
return errors.New("database client not initialized")
} Try / catch
if err := c.FlushAlerts(ctx, maxAge, maxItems); err != nil {
if strings.Contains(err.Error(), "unable to flush alerts older than") {
// transient DB failure; scheduler retries next minute
c.Log.Warningf("alert flush failed, will retry: %s", err)
}
} Prevention
- Keep the alerts table small so DELETEs stay short — a healthy max_age helps.
- For large installs use Postgres/MySQL instead of SQLite to avoid lock contention.
- Do not cancel the scheduler context abruptly mid-flush; use graceful shutdown.
- Apply schema migrations before restarting the service.
When it happens
Trigger: c.Ent.Alert.Delete().Where(...).Exec(ctx) fails: DB connection lost mid-transaction, context canceled/timeout, SQLite lock contention, or schema incompatibility between the ent code and the live DB.
Common situations: Long-running flush competing with a locked SQLite file during a cscli backup; PostgreSQL connection dropped by a proxy idle timeout; context deadline exceeded when the alerts table is very large and the DELETE exceeds a configured timeout.
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
- unable to get alerts count: %w
- while starting FlushAlerts scheduler: %w
- while starting FlushAgentsAndBouncers scheduler: %w
- empty cti key
- no listen_uri or listen_socket specified
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/c1c0acf2172ddfcc.
Report an issue: GitHub.