{"record":{"id":"5babca6653ac72ab","repo":"charmbracelet/crush","slug":"get-usage-by-day-w","errorCode":null,"errorMessage":"get usage by day: %w","messagePattern":"get usage by day: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/stats.go","lineNumber":563,"sourceCode":"\ttotal, err := queries.GetTotalStats(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get total stats: %w\", err)\n\t}\n\tstats.Total = TotalStats{\n\t\tTotalSessions:         total.TotalSessions,\n\t\tTotalPromptTokens:     toInt64(total.TotalPromptTokens),\n\t\tTotalCompletionTokens: toInt64(total.TotalCompletionTokens),\n\t\tTotalTokens:           toInt64(total.TotalPromptTokens) + toInt64(total.TotalCompletionTokens),\n\t\tTotalCost:             toFloat64(total.TotalCost),\n\t\tTotalMessages:         toInt64(total.TotalMessages),\n\t\tAvgTokensPerSession:   toFloat64(total.AvgTokensPerSession),\n\t\tAvgMessagesPerSession: toFloat64(total.AvgMessagesPerSession),\n\t}\n\n\t// Usage by day.\n\tdailyUsage, err := queries.GetUsageByDay(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get usage by day: %w\", err)\n\t}\n\tfor _, d := range dailyUsage {\n\t\tprompt := nullFloat64ToInt64(d.PromptTokens)\n\t\tcompletion := nullFloat64ToInt64(d.CompletionTokens)\n\t\tstats.UsageByDay = append(stats.UsageByDay, DailyUsage{\n\t\t\tDay:              fmt.Sprintf(\"%v\", d.Day),\n\t\t\tPromptTokens:     prompt,\n\t\t\tCompletionTokens: completion,\n\t\t\tTotalTokens:      prompt + completion,\n\t\t\tCost:             d.Cost.Float64,\n\t\t\tSessionCount:     d.SessionCount,\n\t\t})\n\t}\n\n\t// Usage by model.\n\tmodelUsage, err := queries.GetUsageByModel(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get usage by model: %w\", err)","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/stats.go#L545-L581","documentation":"gatherStats fetches per-day usage aggregates via queries.GetUsageByDay and wraps any SQL failure with this message. It is the same SQLite failure family as the other gatherStats errors: the query either cannot execute against the DB or the DB is inaccessible.","triggerScenarios":"GetUsageByDay fails: locked/unreadable SQLite DB, missing or incompatible schema for the daily-aggregation query, or an I/O error reading the database while running `crush stats`.","commonSituations":"Corrupted crush.db after a crash; concurrent crush session holding the write lock; version mismatch between crush binary and an old database schema; --data-dir pointing to an empty/foreign directory.","solutions":["Retry after closing other crush sessions holding the DB","Check DB integrity: `sqlite3 .crush/crush.db 'PRAGMA integrity_check;'`","If the DB is corrupt, restore from backup or delete it to regenerate stats from scratch","Ensure the crush version matches the DB schema version (upgrade/downgrade accordingly)"],"exampleFix":"// before\ncrush stats --data-dir /mnt/nfs/.crush  # locking errors\n// after\ncrush stats --data-dir ~/.local/share/crush  # local fs, reliable SQLite locking","handlingStrategy":"retry","validationCode":"db=\"${CRUSH_DATA_DIR:-.crush}/crush.db\"\nsqlite3 \"$db\" 'PRAGMA integrity_check;' | grep -q '^ok' && [ -r \"$db\" ] && echo \"DB ready\" || { echo \"DB not ready\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":"stats, err := gatherStats(ctx, dbPath)\nif err != nil && strings.Contains(err.Error(), \"get usage by day\") {\n    // transient lock: retry once after backing off\n    time.Sleep(time.Second)\n    stats, err = gatherStats(ctx, dbPath)\n}\nif err != nil { return err }","preventionTips":["Close concurrent crush sessions before gathering stats","Run integrity_check periodically on crush.db","Keep crush binary and DB schema versions in sync","Store .crush locally rather than on network mounts","Maintain a backup of crush.db before risky operations"],"tags":["sqlite","database","sql","cli"],"backgroundTag":"sqlite-database-locked","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}