charmbracelet/crush · error
failed to gather stats from projects: %w
Error message
failed to gather stats from projects: %w
What it means
`crush stats --all` aggregates statistics across all known projects via `gatherStatsFromProjects`. This error wraps any failure of that aggregation — e.g. failing to discover project directories, or errors while reading per-project data — as `failed to gather stats from projects: <cause>`. The underlying cause is in the wrapped error chain.
Source
Thrown at internal/cmd/stats.go:156
func runStats(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
dataDir, _ := cmd.Flags().GetString("data-dir")
crawlDir, _ := cmd.Flags().GetString("crawl-dir")
useAll, _ := cmd.Flags().GetBool("all")
var projectStats []ProjectStats
var err error
switch {
case crawlDir != "":
projectStats, err = crawlForStats(ctx, crawlDir)
if err != nil {
return fmt.Errorf("failed to crawl for stats: %w", err)
}
case useAll:
projectStats, err = gatherStatsFromProjects(ctx)
if err != nil {
return fmt.Errorf("failed to gather stats from projects: %w", err)
}
default:
cfg, err := config.Init("", dataDir, false)
if err != nil {
return fmt.Errorf("failed to initialize config: %w", err)
}
if dataDir == "" {
dataDir = cfg.Config().Options.DataDirectory
}
if shouldEnableMetrics(cfg.Config()) {
event.Init()
}
event.StatsViewed()
conn, err := db.Connect(ctx, dataDir)
if err != nil {
return fmt.Errorf("failed to connect to database: %w", err)View on GitHub (pinned to 7944b8e522)
Solutions
- Read the wrapped cause after the colon to identify the failing project or path.
- Verify your data directory and project directories are readable: check $HOME / --data-dir permissions.
- Retry with a single project via the default mode (no flags) to isolate whether only one project's data is bad.
- Run `crush stats --crawl-dir <specific-dir>` as a fallback to compute stats for a directory you control.
Example fix
// before crush stats --all # failed to gather stats from projects: permission denied // after crush stats --crawl-dir ~/work/project-a # scope to an accessible project
Defensive patterns
Strategy: fallback
Validate before calling
// Verify HOME/data dir is usable before --all
home, err := os.UserHomeDir()
if err != nil {
log.Fatalf("cannot resolve home dir: %v", err)
}
if f, err := os.Open(home); err != nil {
log.Fatalf("home dir not readable: %v", err)
} else {
f.Close()
} Type guard
func isAccessibleDir(path string) bool {
f, err := os.Open(path)
if err != nil {
return false
}
f.Close()
return true
} Try / catch
out, err := exec.Command("crush", "stats", "--all").CombinedOutput()
if err != nil {
if strings.Contains(string(out), "failed to gather stats from projects") {
log.Println("--all aggregation failed; falling back to crawl-dir")
out, err = exec.Command("crush", "stats", "--crawl-dir", ".").CombinedOutput()
}
if err != nil {
log.Fatalf("stats failed: %v: %s", err, out)
}
} Prevention
- Run as a user with read access to the data and project directories.
- If HOME differs (service accounts), pass --data-dir explicitly.
- Isolate bad project data by running single-project stats before --all.
- Check filesystem mount health (read-only remounts) before large aggregations.
When it happens
Trigger: Running `crush stats --all` where `gatherStatsFromProjects(ctx)` at internal/cmd/stats.go:154 returns an error, typically because it cannot enumerate or read the project directories / their data under the user's data or home directories.
Common situations: Home directory or data directory unreadable (permissions, read-only mount); projects registry missing or malformed; disk I/O errors while reading many project DBs; running under a service account with a different HOME.
Related errors
- failed to crawl for stats: %w
- failed to tail log file: %v
- failed to change directory: %v
- no data available: no projects found
- no data available: no sessions found in database
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/fbb1ba3ad5a08908.
Report an issue: GitHub.