crowdsecurity/crowdsec · error
getting unsent usage metrics: %w
Error message
getting unsent usage metrics: %w
What it means
GetUnsentMetrics returns metric rows not yet pushed to CAPI, ordered by ID with a limit. This error wraps a failing SELECT; having zero unsent rows is not an error — it returns an empty slice with nil error.
Source
Thrown at pkg/database/metrics.go:90
}
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)
return nil, fmt.Errorf("getting unsent usage metrics: %w", err)
}
return metrics, nil
}
// MarkStaleUsageMetricsAsSent gives up on metrics too old to be worth pushing, so a CAPI outage
// cannot leave a growing backlog behind. The rows live on until the age flush, for cscli.
func (c *Client) MarkStaleUsageMetricsAsSent(ctx context.Context, before time.Time) (int, error) {
updated, err := c.Ent.Metric.Update().
Where(
metric.PushedAtIsNil(),
metric.ReceivedAtLT(before),
).
SetPushedAt(time.Now().UTC()).
Save(ctx)
if err != nil {
c.Log.Warningf("MarkStaleUsageMetricsAsSent: %s", err)
return 0, fmt.Errorf("marking stale usage metrics as sent: %w", err)View on GitHub (pinned to 909b515798)
Solutions
- Inspect the Warningf log 'GetUnsentMetrics: <err>' for the underlying error.
- Fix DB permissions/ownership or relocate off network filesystems.
- Integrity-check and restore the DB if corrupt.
- Retry — the push loop invokes this periodically, so transient failures recover automatically.
Example fix
// before
metrics, err := c.GetUnsentMetrics(ctx, 100)
if err != nil { return err }
// after: empty is normal
if err != nil { return fmt.Errorf("unsent metrics: %w", err) }
if len(metrics) == 0 { return nil } Defensive patterns
Strategy: retry
Try / catch
metrics, err := client.GetUnsentMetrics(ctx, limit)
if err != nil {
log.Warnf("unsent metrics query failed, retrying next tick: %v", err)
return nil
}
if len(metrics) == 0 { return nil } Prevention
- Run the fetch periodically and retry transient failures.
- Distinguish empty result from error.
- Fix permissions after moving/restoring the data directory.
- Keep the DB off network filesystems to avoid lock errors.
When it happens
Trigger: Calling GetUnsentMetrics (usage-metrics push loop or cscli usage listing) when the query fails: DB file locked/unreadable, corrupted SQLite DB, disk I/O error, canceled context.
Common situations: Concurrent crowdsec/cscli access causing SQLite lock timeouts; corrupted DB after unclean shutdown; permission problems after moving the data directory.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- getting LP usage metrics by origin %s: %w
- getting bouncer usage metrics by name %s: %w
- storing metrics snapshot for '%s' at %s: %w
- marking usage metrics as sent: %w
- marking stale usage metrics as sent: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b01b67b115b823de.
Report an issue: GitHub.