crowdsecurity/crowdsec · error · DeleteFail
alert graph delete batch: %w
Error message
alert graph delete batch: %w
What it means
In DeleteAlertGraphBatch, after the associated decisions are removed, the alerts themselves are bulk-deleted. This error means that final Alert.Delete() call failed, so the alerts (and possibly already-deleted decisions) are in a partially cleaned state. It wraps the DeleteFail sentinel indicating a database delete failure.
Source
Thrown at pkg/database/alerts.go:925
_, err = c.Ent.Meta.Delete().
Where(meta.HasOwnerWith(alert.IDIn(idList...))).Exec(ctx)
if err != nil {
c.Log.Warningf("DeleteAlertGraphBatch : %s", err)
return 0, fmt.Errorf("alert graph delete batch meta: %w", DeleteFail)
}
_, err = c.Ent.Decision.Delete().
Where(decision.HasOwnerWith(alert.IDIn(idList...))).Exec(ctx)
if err != nil {
c.Log.Warningf("DeleteAlertGraphBatch : %s", err)
return 0, fmt.Errorf("alert graph delete batch decisions: %w", DeleteFail)
}
deleted, err := c.Ent.Alert.Delete().
Where(alert.IDIn(idList...)).Exec(ctx)
if err != nil {
c.Log.Warningf("DeleteAlertGraphBatch : %s", err)
return deleted, fmt.Errorf("alert graph delete batch: %w", DeleteFail)
}
c.Log.Debug("Done batch delete alerts")
return deleted, nil
}
func (c *Client) DeleteAlertGraph(ctx context.Context, alertItem *ent.Alert) error {
// delete the associated events
_, err := c.Ent.Event.Delete().
Where(event.HasOwnerWith(alert.IDEQ(alertItem.ID))).Exec(ctx)
if err != nil {
c.Log.Warningf("DeleteAlertGraph : %s", err)
return fmt.Errorf("event with alert ID '%d': %w", alertItem.ID, DeleteFail)
}
// delete the associated meta
_, err = c.Ent.Meta.Delete().View on GitHub (pinned to 909b515798)
Solutions
- Inspect the warning log 'DeleteAlertGraphBatch : %s' for the underlying DB error
- Retry the batch delete — decisions were already removed, remaining alerts should delete cleanly
- Check DB grants and connection stability
- Reduce batch size to avoid long-running transactions/locks
Example fix
// before
deleted, err := client.DeleteAlertGraphBatch(ctx, ids)
// after
deleted, err := client.DeleteAlertGraphBatch(ctx, ids)
if err != nil && errors.Is(err, entdb.DeleteFail) {
log.Warnf("partial delete: %d alerts affected, retry", deleted)
} Defensive patterns
Strategy: retry
Validate before calling
if err := client.Ent.Alert.Query().Where(alert.IDIn(ids...)).Exist(ctx); err != nil {
return fmt.Errorf("cannot reach alerts table: %w", err)
} Try / catch
deleted, err := client.DeleteAlertGraphBatch(ctx, ids)
if errors.Is(err, entdb.DeleteFail) {
// decisions may already be gone; safe to retry the batch
deleted, err = client.DeleteAlertGraphBatch(ctx, ids)
} Prevention
- Treat batch deletes as retryable — the query filters by ID, so retries are idempotent
- Avoid running huge batches during peak DB load
- Ensure the alerts table has no FK rows blocking deletion
- Watch for lock contention with concurrent LAPI requests
When it happens
Trigger: c.DeleteAlertGraphBatch(ctx, idList) is called, decision deletion succeeded, but Alert.Delete().Where(alert.IDIn(idList...)) fails: connection loss between the two statements, lock contention on alerts, insufficient DELETE grants, or context cancellation.
Common situations: Large batch deletes timing out under lock contention while a machine still streams alerts; DB failover mid-request on LAPI; low-privileged DB user missing DELETE on alerts.
Related errors
- alert graph delete batch decisions: %w
- hard delete decisions with provided filter: %w
- could not delete alerts: %w
- unable to delete
- while getting allowlist %s: %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/4b03ee63ffc93895.
Report an issue: GitHub.