charmbracelet/crush · error
get usage by day: %w
Error message
get usage by day: %w
What it means
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.
Source
Thrown at internal/cmd/stats.go:563
total, err := queries.GetTotalStats(ctx)
if err != nil {
return nil, fmt.Errorf("get total stats: %w", err)
}
stats.Total = TotalStats{
TotalSessions: total.TotalSessions,
TotalPromptTokens: toInt64(total.TotalPromptTokens),
TotalCompletionTokens: toInt64(total.TotalCompletionTokens),
TotalTokens: toInt64(total.TotalPromptTokens) + toInt64(total.TotalCompletionTokens),
TotalCost: toFloat64(total.TotalCost),
TotalMessages: toInt64(total.TotalMessages),
AvgTokensPerSession: toFloat64(total.AvgTokensPerSession),
AvgMessagesPerSession: toFloat64(total.AvgMessagesPerSession),
}
// Usage by day.
dailyUsage, err := queries.GetUsageByDay(ctx)
if err != nil {
return nil, fmt.Errorf("get usage by day: %w", err)
}
for _, d := range dailyUsage {
prompt := nullFloat64ToInt64(d.PromptTokens)
completion := nullFloat64ToInt64(d.CompletionTokens)
stats.UsageByDay = append(stats.UsageByDay, DailyUsage{
Day: fmt.Sprintf("%v", d.Day),
PromptTokens: prompt,
CompletionTokens: completion,
TotalTokens: prompt + completion,
Cost: d.Cost.Float64,
SessionCount: d.SessionCount,
})
}
// Usage by model.
modelUsage, err := queries.GetUsageByModel(ctx)
if err != nil {
return nil, fmt.Errorf("get usage by model: %w", err)View on GitHub (pinned to 7944b8e522)
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)
Example fix
// before crush stats --data-dir /mnt/nfs/.crush # locking errors // after crush stats --data-dir ~/.local/share/crush # local fs, reliable SQLite locking
Defensive patterns
Strategy: retry
Validate before calling
db="${CRUSH_DATA_DIR:-.crush}/crush.db"
sqlite3 "$db" 'PRAGMA integrity_check;' | grep -q '^ok' && [ -r "$db" ] && echo "DB ready" || { echo "DB not ready" >&2; exit 1; } Try / catch
stats, err := gatherStats(ctx, dbPath)
if err != nil && strings.Contains(err.Error(), "get usage by day") {
// transient lock: retry once after backing off
time.Sleep(time.Second)
stats, err = gatherStats(ctx, dbPath)
}
if err != nil { return err } Prevention
- 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
When it happens
Trigger: 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`.
Common situations: 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.
Related errors
- get total stats: %w
- get usage by model: %w
- get usage by hour: %w
- get usage by day of week: %w
- get recent activity: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/5babca6653ac72ab.
Report an issue: GitHub.