charmbracelet/crush · error
get usage by hour: %w
Error message
get usage by hour: %w
What it means
gatherStats fetches hourly usage distribution via queries.GetUsageByHour and wraps any SQL failure with this message. Same root causes as the other gatherStats queries: the SQLite database must be open, unlocked, and schema-compatible for the query to succeed.
Source
Thrown at internal/cmd/stats.go:594
}
// Usage by model.
modelUsage, err := queries.GetUsageByModel(ctx)
if err != nil {
return nil, fmt.Errorf("get usage by model: %w", err)
}
for _, m := range modelUsage {
stats.UsageByModel = append(stats.UsageByModel, ModelUsage{
Model: m.Model,
Provider: m.Provider,
MessageCount: m.MessageCount,
})
}
// Usage by hour.
hourlyUsage, err := queries.GetUsageByHour(ctx)
if err != nil {
return nil, fmt.Errorf("get usage by hour: %w", err)
}
for _, h := range hourlyUsage {
stats.UsageByHour = append(stats.UsageByHour, HourlyUsage{
Hour: int(h.Hour),
SessionCount: h.SessionCount,
})
}
// Usage by day of week.
dowUsage, err := queries.GetUsageByDayOfWeek(ctx)
if err != nil {
return nil, fmt.Errorf("get usage by day of week: %w", err)
}
for _, d := range dowUsage {
stats.UsageByDayOfWeek = append(stats.UsageByDayOfWeek, DayOfWeekUsage{
DayOfWeek: int(d.DayOfWeek),
DayName: dayNames[int(d.DayOfWeek)],
SessionCount: d.SessionCount,View on GitHub (pinned to 7944b8e522)
Solutions
- Ensure no concurrent crush process holds the write lock, then rerun
- Confirm the DB exists and migrations are complete for your crush version
- If corrupted, remove or restore the DB and regenerate stats
- Use a local (non-NFS) data directory for reliable SQLite behavior
Example fix
// before crush stats # get usage by hour: database is locked (another session running) // after wait for/close the running crush session, then: crush stats
Defensive patterns
Strategy: retry
Validate before calling
db="${CRUSH_DATA_DIR:-.crush}/crush.db"
if fuser "$db" >/dev/null 2>&1; then echo "DB in use; wait and retry" >&2; exit 1; fi
sqlite3 "$db" 'PRAGMA integrity_check;' | grep -q ok || { echo "Corrupt DB" >&2; exit 1; } Try / catch
if err := gatherStats(ctx, dbPath); err != nil {
if strings.Contains(err.Error(), "get usage by hour") {
select {
case <-time.After(time.Second):
return gatherStats(ctx, dbPath) // one retry for transient lock
}
}
return err
} Prevention
- Serialize crush usage per data dir; avoid concurrent writers
- Use a local disk for the data dir
- Restore from backup rather than using a partially-corrupt DB
- Complete migrations (run the matching crush version) before stats
- Check for disk-full conditions after crashes
When it happens
Trigger: GetUsageByHour fails: DB file locked, missing, unreadable, corrupted, or the prepared statement fails due to schema drift between crush versions.
Common situations: DB held by a long-running crush session; .crush on a flaky network mount; interrupted upgrade leaving partial migration; --data-dir pointing at a directory without a valid crush.db.
Related errors
- get total stats: %w
- get usage by day: %w
- get usage by model: %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/9976441eae496b02.
Report an issue: GitHub.