{"record":{"id":"78ecb5d82efb2164","repo":"Wei-Shaw/sub2api","slug":"failed-to-get-dashboard-statistics","errorCode":null,"errorMessage":"failed to get dashboard statistics","messagePattern":"failed to get dashboard statistics","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"backend/internal/handler/admin/dashboard_snapshot_v2_handler.go","lineNumber":168,"sourceCode":"func (h *DashboardHandler) buildSnapshotV2Response(\n\tctx context.Context,\n\tstartTime, endTime time.Time,\n\tgranularity string,\n\tfilters *dashboardSnapshotV2Filters,\n\tincludeStats, includeTrend, includeModels, includeGroups, includeUsersTrend bool,\n\tusersTrendLimit int,\n) (*dashboardSnapshotV2Response, error) {\n\tresp := &dashboardSnapshotV2Response{\n\t\tGeneratedAt: time.Now().UTC().Format(time.RFC3339),\n\t\tStartDate:   startTime.Format(\"2006-01-02\"),\n\t\tEndDate:     endTime.Add(-24 * time.Hour).Format(\"2006-01-02\"),\n\t\tGranularity: granularity,\n\t}\n\n\tif includeStats {\n\t\tstats, err := h.dashboardService.GetDashboardStats(ctx)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"failed to get dashboard statistics\")\n\t\t}\n\t\tresp.Stats = &dashboardSnapshotV2Stats{\n\t\t\tDashboardStats: *stats,\n\t\t\tUptime:         int64(time.Since(h.startTime).Seconds()),\n\t\t}\n\t}\n\n\tif includeTrend {\n\t\ttrend, _, err := h.getUsageTrendCached(\n\t\t\tctx,\n\t\t\tstartTime,\n\t\t\tendTime,\n\t\t\tgranularity,\n\t\t\tfilters.UserID,\n\t\t\tfilters.APIKeyID,\n\t\t\tfilters.AccountID,\n\t\t\tfilters.GroupID,\n\t\t\tfilters.Model,","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/Wei-Shaw/sub2api/blob/073e92d17178a1ccdb0a27017f572f10c9c7ab62/backend/internal/handler/admin/dashboard_snapshot_v2_handler.go#L150-L186","documentation":"Returned while assembling the v2 dashboard snapshot when includeStats is true and the underlying dashboardService.GetDashboardStats call fails. The original error is discarded and replaced with this generic message, so the real cause (usually a database failure) is only visible in server logs. It is a transient/infrastructure error, not a request-format problem.","triggerScenarios":"GET /admin dashboard snapshot v2 endpoint with stats included (include_stats / default true) while the usage-stats database is unreachable, timing out, or has a schema/lock problem.","commonSituations":"Database connection pool exhaustion under load; migrations leaving stats tables missing; long-running aggregate queries hitting statement timeouts after data growth.","solutions":["Retry the snapshot request after a short delay — most causes are transient DB issues","Check backend logs for the underlying GetDashboardStats error at that timestamp","Verify database connectivity, pool limits, and that usage stats tables exist and are migrated","As a workaround, request the snapshot without stats (exclude the stats section) to get trend/model data"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// TS: retry with backoff, degrade gracefully\ntry { snapshot = await getSnapshotV2({ includeStats: true }); }\ncatch (e) {\n  if (e.message === 'failed to get dashboard statistics') {\n    snapshot = await retry(async () => getSnapshotV2({ includeStats: false }), { tries: 3 });\n  } else throw e;\n}","preventionTips":["Treat snapshot 5xx/generic failures as transient: retry with exponential backoff and jitter","Monitor DB health and pool saturation on the backend","Cache last-good snapshot client-side so a failed fetch degrades instead of blanking dashboards"],"tags":["dashboard","database","admin","snapshot"],"backgroundTag":null,"analyzedSha":"073e92d17178a1ccdb0a27017f572f10c9c7ab62","analyzedAt":"2026-08-15T14:33:00.750Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}