crowdsecurity/crowdsec · error · DeleteFail

decision with alert ID '%d': %w

Error message

decision with alert ID '%d': %w

What it means

DeleteAlertGraph deletes the alert's decisions after events and meta. This error means the Decision DELETE failed, leaving events/meta already removed but decisions and the alert intact. Wraps the DeleteFail sentinel.

Source

Thrown at pkg/database/alerts.go:955

	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)
	}

	// delete the alert
	err = c.Ent.Alert.DeleteOne(alertItem).Exec(ctx)
	if err != nil {
		c.Log.Warningf("DeleteAlertGraph : %s", err)
		return fmt.Errorf("alert with ID '%d': %w", alertItem.ID, DeleteFail)
	}

	return nil
}

func (c *Client) DeleteAlertByID(ctx context.Context, id int) error {
	alertItem, err := c.Ent.Alert.Query().Where(alert.IDEQ(id)).Only(ctx)
	if err != nil {
		return err
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the 'DeleteAlertGraph : %s' warning for the root cause
  2. Retry DeleteAlertByID; the operation is safe to re-run
  3. Check for lock contention with active bouncer queries on decisions
  4. Verify DB user DELETE grants on decisions
Defensive patterns

Strategy: try-catch

Validate before calling

// decisions may be actively read by bouncers; check DB lock pressure first
n, err := client.Ent.Decision.Query().Where(decision.HasOwnerWith(alert.IDEQ(id))).Count(ctx)
if err != nil { /* DB unhealthy, skip delete */ }

Try / catch

err := client.DeleteAlertByID(ctx, id)
if err != nil && errors.Is(err, entdb.DeleteFail) {
    // decisions stage failed; check for bouncer read contention
}

Prevention

When it happens

Trigger: DeleteAlertByID(ctx, id) -> DeleteAlertGraph: Decision.Delete().Where(decision.HasOwnerWith(alert.IDEQ(alertItem.ID))) fails — DB unavailable, FK/lock issues from an active bouncer reading decisions, or missing grants.

Common situations: Lock contention because bouncers continuously SELECT from decisions while LAPI deletes; DB connection loss; migration mismatch on the decisions table.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/93e96d241d1caa9f. Report an issue: GitHub.