crowdsecurity/crowdsec · error · DeleteFail
event with alert ID '%d': %w
Error message
event with alert ID '%d': %w
What it means
DeleteAlertGraph removes all rows owned by one alert (events, meta, decisions, then the alert). This error means deleting the alert's Event rows failed, so the graph delete aborts with nothing else removed. The alert ID is embedded in the message and the cause is wrapped with the DeleteFail sentinel.
Source
Thrown at pkg/database/alerts.go:939
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().
Where(meta.HasOwnerWith(alert.IDEQ(alertItem.ID))).Exec(ctx)
if err != nil {
c.Log.Warningf("DeleteAlertGraph : %s", err)
return fmt.Errorf("meta with alert ID '%d': %w", alertItem.ID, DeleteFail)
}
// delete the associated decisions
_, err = c.Ent.Decision.Delete().
Where(decision.HasOwnerWith(alert.IDEQ(alertItem.ID))).Exec(ctx)
if err != nil {
c.Log.Warningf("DeleteAlertGraph : %s", err)
return fmt.Errorf("decision with alert ID '%d': %w", alertItem.ID, DeleteFail)
}
View on GitHub (pinned to 909b515798)
Solutions
- Read the underlying error logged as 'DeleteAlertGraph : %s'
- Verify connectivity and DELETE grants on the events table
- Retry the delete for the same alert ID
- Consider pruning events separately if the table is very large
Example fix
// before
err := client.DeleteAlertByID(ctx, alertID)
// after
if err := client.DeleteAlertByID(ctx, alertID); err != nil {
if errors.Is(err, entdb.DeleteFail) {
log.Errorf("failed deleting events for alert %d: %v", alertID, err)
}
} Defensive patterns
Strategy: try-catch
Validate before calling
exists, err := client.Ent.Alert.Query().Where(alert.IDEQ(id)).Exist(ctx)
if err != nil || !exists { return } // nothing to delete Try / catch
err := client.DeleteAlertByID(ctx, id)
if err != nil && errors.Is(err, entdb.DeleteFail) {
// events stage failed; verify DB health before retry
} Prevention
- Verify the DB user can DELETE from events
- Prune old alerts regularly so event tables stay small
- Avoid deleting alerts while bulk imports are running
- Check 'DeleteAlertGraph' warnings in logs for early signs of DB trouble
When it happens
Trigger: DeleteAlertByID(ctx, id) -> DeleteAlertGraph: Event.Delete().Where(event.HasOwnerWith(alert.IDEQ(alertItem.ID))) fails due to DB unavailability, permission, lock, or cancelled context.
Common situations: cscli alerts delete on a machine whose DB connection has dropped; huge event tables causing long lock waits and timeouts; DB user without DELETE on events.
Related errors
- unable to delete
- alert graph delete batch events: %w
- alert graph delete batch meta: %w
- alert graph delete batch decisions: %w
- alert graph delete batch: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/7b8d9660f84fb331.
Report an issue: GitHub.