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

  1. Read the wrapped cause after the colon to identify the failing project or path.
  2. Verify your data directory and project directories are readable: check $HOME / --data-dir permissions.
  3. Retry with a single project via the default mode (no flags) to isolate whether only one project's data is bad.
  4. 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

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


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