charmbracelet/crush · error

get hour day heatmap: %w

Error message

get hour day heatmap: %w

What it means

gatherStats wraps a failure from queries.GetHourDayHeatmap(ctx), the sqlc query that groups sessions by day-of-week and hour for the heatmap section of the stats report. The underlying database error is preserved via %w. Same failure family as the other stats queries in this function.

Source

Thrown at internal/cmd/stats.go:656

	// 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.
	heatmap, err := queries.GetHourDayHeatmap(ctx)
	if err != nil {
		return nil, fmt.Errorf("get hour day heatmap: %w", err)
	}
	for _, h := range heatmap {
		stats.HourDayHeatmap = append(stats.HourDayHeatmap, HourDayHeatmapPt{
			DayOfWeek:    int(h.DayOfWeek),
			Hour:         int(h.Hour),
			SessionCount: h.SessionCount,
		})
	}

	return stats, nil
}

func toInt64(v any) int64 {
	switch val := v.(type) {
	case int64:
		return val
	case float64:
		return int64(val)

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Inspect the wrapped cause for the exact SQLite error (locked, corrupt, no such table).
  2. Stop other crush processes that may lock the database and retry.
  3. Let crush run migrations by starting it normally before using `crush stats`.
  4. If the database is corrupt, restore a backup or delete/recreate the DB.
Defensive patterns

Strategy: try-catch

Try / catch

stats, err := gatherStats(ctx, queries)
if err != nil {
    if errors.Is(err, sqlite.ErrLocked) || errors.Is(err, context.DeadlineExceeded) {
        return retryWithBackoff(func() error { _, err := gatherStats(ctx, queries); return err })
    }
    return err
}

Prevention

When it happens

Trigger: Running `crush stats` when the heatmap aggregation query fails: locked/corrupt SQLite DB, unmigrated schema, I/O error while reading session rows.

Common situations: Concurrent crush session holding the SQLite write lock; corrupted history DB; older DB file missing tables the new query expects.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/ab29ba0177eb3536. Report an issue: GitHub.