crowdsecurity/crowdsec · error
marking usage metrics as sent: %w
Error message
marking usage metrics as sent: %w
What it means
MarkUsageMetricsAsSent sets pushed_at on the metric rows with the given IDs. This error wraps a failing bulk UPDATE. Note the Save count is ignored, so a zero-row update is still 'success' — only a database-level failure produces this error.
Source
Thrown at pkg/database/metrics.go:71
metric.PushedAtIsNil(),
).
All(ctx)
if err != nil {
c.Log.Warningf("GetBouncerUsageMetricsByName: %s", err)
return nil, fmt.Errorf("getting bouncer usage metrics by name %s: %w", bouncerName, err)
}
return metrics, nil
}
func (c *Client) MarkUsageMetricsAsSent(ctx context.Context, ids []int) error {
_, err := c.Ent.Metric.Update().
Where(metric.IDIn(ids...)).
SetPushedAt(time.Now().UTC()).
Save(ctx)
if err != nil {
c.Log.Warningf("MarkUsageMetricsAsSent: %s", err)
return fmt.Errorf("marking usage metrics as sent: %w", err)
}
return nil
}
// GetUnsentMetrics returns metrics not pushed to CAPI yet, across all sources, ordered by id.
// Callers walk the backlog by passing back the id of the last row they consumed.
func (c *Client) GetUnsentMetrics(ctx context.Context, afterID int, limit int) ([]*ent.Metric, error) {
metrics, err := c.Ent.Metric.Query().
Where(
metric.PushedAtIsNil(),
metric.IDGT(afterID),
).
Order(ent.Asc(metric.FieldID)).
Limit(limit).
All(ctx)
if err != nil {
c.Log.Warningf("GetUnsentMetrics: %s", err)View on GitHub (pinned to 909b515798)
Solutions
- Check the Warningf log 'MarkUsageMetricsAsSent: <err>' for the real cause.
- Resolve writer contention (WAL mode / single crowdsec process per DB).
- Free disk space; verify the DB integrity.
- Re-run the send loop — unsent rows will be re-fetched by GetUnsentMetrics, so a failed mark just risks a duplicate push, not data loss.
Example fix
// before: error only
if err := c.MarkUsageMetricsAsSent(ctx, ids); err != nil { log.Error(err) }
// after: tolerate failure so push loop keeps going (rows may be pushed twice at worst)
if err := c.MarkUsageMetricsAsSent(ctx, ids); err != nil {
log.Warnf("could not mark metrics sent, they may be re-pushed: %v", err)
} Defensive patterns
Strategy: retry
Validate before calling
// ensure the ids are non-empty before issuing the update
if len(ids) == 0 { return nil } Try / catch
err := client.MarkUsageMetricsAsSent(ctx, ids)
if err != nil {
log.Warnf("mark-sent failed; rows may be re-pushed next cycle: %v", err)
// do not abort the loop — at worst metrics get pushed twice
} Prevention
- Make the push loop idempotent — a failed mark is recoverable.
- Resolve SQLite writer contention (WAL, single process).
- Monitor disk space; full disks cause UPDATE failures.
- Log the unwrapped cause from the Warningf line.
When it happens
Trigger: Calling MarkUsageMetricsAsSent (from sendUsageMetricsBatch after a successful CAPI push) when the UPDATE fails: DB write lock held by another process, disk full, corrupted DB, or context cancellation.
Common situations: SQLite 'database is locked' while the agent writes alert rows concurrently; disk quota exceeded on the metrics volume after a large usage batch.
Related errors
- marking stale usage metrics as sent: %w
- storing metrics snapshot for '%s' at %s: %w
- getting LP usage metrics by origin %s: %w
- getting bouncer usage metrics by name %s: %w
- getting unsent usage metrics: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/5361adc4b61aa1e1.
Report an issue: GitHub.