crowdsecurity/crowdsec · error
hard delete decisions with provided filter: %w
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.
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)
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: %w
- alert graph delete batch: %w
- expire decisions with provided filter: %w
- expire decisions with provided filter: %w: %w
- could not delete alerts: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/924ec40ef78e32b1.
Report an issue: GitHub.