Wei-Shaw/sub2api · error

failed to get user usage trend

Error message

failed to get user usage trend

What it means

Returned while assembling the v2 dashboard snapshot when includeUsersTrend is true and h.getUserUsageTrendCached(...) fails. Unlike the other sections it takes only granularity and a usersTrendLimit, so failures are almost purely storage-side (query error/timeout), not filter-related.

Source

Thrown at backend/internal/handler/admin/dashboard_snapshot_v2_handler.go:242

			filters.UserID,
			filters.APIKeyID,
			filters.AccountID,
			filters.GroupID,
			filters.RequestType,
			filters.Stream,
			filters.BillingType,
			filters.UpstreamModelMismatch,
		)
		if err != nil {
			return nil, errors.New("failed to get group statistics")
		}
		resp.Groups = groups
	}

	if includeUsersTrend {
		usersTrend, _, err := h.getUserUsageTrendCached(ctx, startTime, endTime, granularity, usersTrendLimit)
		if err != nil {
			return nil, errors.New("failed to get user usage trend")
		}
		resp.UsersTrend = usersTrend
	}

	return resp, nil
}

func parseDashboardSnapshotV2Filters(c *gin.Context) (*dashboardSnapshotV2Filters, error) {
	filters := &dashboardSnapshotV2Filters{
		Model: strings.TrimSpace(c.Query("model")),
	}

	if userIDStr := strings.TrimSpace(c.Query("user_id")); userIDStr != "" {
		id, err := strconv.ParseInt(userIDStr, 10, 64)
		if err != nil {
			return nil, err
		}
		filters.UserID = id

View on GitHub (pinned to 073e92d171)

Solutions

  1. Retry the request
  2. Lower usersTrendLimit or use a coarser granularity
  3. Shorten the date range
  4. Check backend logs for the underlying user-trend query error
Defensive patterns

Strategy: retry

Validate before calling

// Validate limit/granularity before the call
if (!Number.isInteger(usersTrendLimit) || usersTrendLimit <= 0 || usersTrendLimit > 100) {
  usersTrendLimit = 50;
}

Try / catch

// TS
try { usersTrend = (await getSnapshotV2({ includeUsersTrend: true, start, end, granularity, usersTrendLimit })).usersTrend; }
catch (e) {
  if (e.message === 'failed to get user usage trend') {
    usersTrend = (await withBackoff(() => getSnapshotV2({ includeUsersTrend: true, start, end, granularity, usersTrendLimit: 20 }))).usersTrend;
  } else throw e;
}

Prevention

When it happens

Trigger: GET dashboard snapshot v2 with the users-trend section included while the per-user trend aggregation over the window fails or times out.

Common situations: High user counts with fine granularity; a large usersTrendLimit forcing big per-user series; DB pressure from concurrent dashboards.

Related errors


AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15). Data as JSON: /api/errors/1dbdf34940d43fed. Report an issue: GitHub.