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

  1. Inspect the Warningf log 'GetUnsentMetrics: <err>' for the underlying error.
  2. Fix DB permissions/ownership or relocate off network filesystems.
  3. Integrity-check and restore the DB if corrupt.
  4. 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

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


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