crowdsecurity/crowdsec · error
hard delete decisions with provided filter
Error message
hard delete decisions with provided filter: %w
What it means
deleteDecisionBatch is the batched worker used by DeleteDecisions for hard deletions: it runs an ent Delete().Where(IDIn(ids...)).Exec(ctx). If the DELETE statement fails, the raw DB error is wrapped with this message, meaning rows could not be removed from the database.
Solutions
- Verify the DB is writable by the crowdsec user and not locked by another process
- Retry; batches are independent so already-deleted rows are simply gone
- Reduce batch size to shorten each transaction and lower contention
- Check the wrapped inner error for the exact SQL/driver failure
Example fix
// before // running: crowdsec with a read-only sqlite file // after # chown crowdsec:crowdsec /var/lib/crowdsec/data/crowdsec.db && chmod u+w /var/lib/crowdsec/data/crowdsec.db
Defensive patterns
Strategy: retry
Validate before calling
if len(ids) == 0 { return nil }
if !dbWritable() { return errors.New("database is read-only") } Try / catch
if _, err := client.DeleteDecisions(ctx, decisions, hardDelete); err != nil {
if strings.Contains(err.Error(), "hard delete decisions with provided filter") {
// inspect wrapped DB error; retry after checking locks/permissions
}
return err
} Prevention
- Verify the crowdsec process owns and can write the DB file
- Avoid deleting while bulk imports run to reduce lock contention
- Use modest batch sizes for hard deletes
When it happens
Trigger: Ent Delete() failing for a batch of decision IDs: DB unreachable, foreign-key or trigger errors, context cancelled, lock contention with concurrent writers.
Common situations: cscli decisions delete --all racing with an active import; SQLite locked by another process; DB read-only (permissions) or disk full.
Related errors
- alert graph delete batch decisions
- alert graph delete batch
- could not delete alerts
- expire decisions with provided filter
- expire decisions with provided filter
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/924ec40ef78e32b1.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/database/decisions.go:336
return err
}
total += rows
return nil
})
return total, err
}
// deleteDecisionBatch removes the decisions as a single operation.
func (c *Client) deleteDecisionBatch(ctx context.Context, batch []*ent.Decision) (int, error) {
ids := decisionIDs(batch)
rows, err := c.Ent.Decision.
Delete().
Where(decision.IDIn(ids...)).
Exec(ctx)
if err != nil {
return 0, fmt.Errorf("hard delete decisions with provided filter: %w", err)
}
return rows, nil
}
// DeleteDecisions removes a list of decisions from the database,
// in multiple operations if len(decisions) > decisionDeleteBulkSize.
// It returns the number of impacted decisions for the CAPI/PAPI, even in case of error.
func (c *Client) DeleteDecisions(ctx context.Context, decisions []*ent.Decision) (int, error) {
if len(decisions) == 0 {
return 0, nil
}
total := 0
err := slicetools.Batch(ctx, decisions, decisionDeleteBulkSize, func(ctx context.Context, batch []*ent.Decision) error {
rows, err := c.deleteDecisionBatch(ctx, batch)
if err != nil {
return errView on GitHub (pinned to 909b515798)