charmbracelet/crush · error
get average response time: %w
Error message
get average response time: %w
What it means
gatherStats fetches the average assistant response time via queries.GetAverageResponseTime and wraps any SQL failure with this message. The query computes a millisecond average from message timestamps; failures are database-level (lock, access, corruption, schema), not data-quality issues.
Source
Thrown at internal/cmd/stats.go:635
// Recent activity (last 30 days).
recent, err := queries.GetRecentActivity(ctx)
if err != nil {
return nil, fmt.Errorf("get recent activity: %w", err)
}
for _, r := range recent {
stats.RecentActivity = append(stats.RecentActivity, DailyActivity{
Day: fmt.Sprintf("%v", r.Day),
SessionCount: r.SessionCount,
TotalTokens: nullFloat64ToInt64(r.TotalTokens),
Cost: r.Cost.Float64,
})
}
// Average response time.
avgResp, err := queries.GetAverageResponseTime(ctx)
if err != nil {
return nil, fmt.Errorf("get average response time: %w", err)
}
stats.AvgResponseTimeMs = toFloat64(avgResp) * 1000
// Tool usage.
toolUsage, err := queries.GetToolUsage(ctx)
if err != nil {
return nil, fmt.Errorf("get tool usage: %w", err)
}
for _, t := range toolUsage {
if name, ok := t.ToolName.(string); ok && name != "" {
stats.ToolUsage = append(stats.ToolUsage, ToolUsage{
ToolName: name,
CallCount: t.CallCount,
})
}
}
// Hour/day heatmap.View on GitHub (pinned to 7944b8e522)
Solutions
- Ensure no other crush instance is writing, then rerun
- Verify DB readability and integrity; restore or regenerate a corrupt DB
- Match the crush binary version to the DB schema (reinstall/upgrade)
- Move .crush to a local filesystem if it currently lives on NFS/network storage
Example fix
// before crush stats # get average response time: disk I/O error // after sqlite3 .crush/crush.db 'PRAGMA integrity_check;' # if corrupt: restore or delete crush.db, then rerun
Defensive patterns
Strategy: retry
Validate before calling
db="${CRUSH_DATA_DIR:-.crush}/crush.db"
if ! sqlite3 "$db" 'SELECT count(*) FROM messages;' >/dev/null 2>&1; then
echo "Sessions DB not queryable (locked/missing/corrupt): $db" >&2
exit 1
fi Try / catch
if err := gatherStats(ctx, dbPath); err != nil {
if strings.Contains(err.Error(), "get average response time") && strings.Contains(err.Error(), "locked") {
time.Sleep(1 * time.Second)
return gatherStats(ctx, dbPath)
}
return err
} Prevention
- Run stats when no crush session is actively writing
- Keep the data dir on a local filesystem with working SQLite locks
- Maintain the crush binary/DB schema in sync
- Schedule backups of crush.db and verify integrity after crashes
- Avoid sudo runs that alter DB ownership
When it happens
Trigger: GetAverageResponseTime fails: SQLite DB locked or unreadable, corrupt database file, or the prepared statement failing due to missing/mismatched schema in the sessions DB.
Common situations: Concurrent crush sessions contending for the write lock; crash-interrupted writes corrupting crush.db; schema/version mismatch; DB on network storage with unreliable locking.
Related errors
- get total stats: %w
- get usage by day: %w
- get usage by model: %w
- get usage by hour: %w
- get usage by day of week: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/214b312d1b141136.
Report an issue: GitHub.