charmbracelet/crush · error
failed to crawl for stats: %w
Error message
failed to crawl for stats: %w
What it means
`crush stats --crawl-dir <dir>` walks the given directory tree to compute project statistics via `crawlForStats`. This error wraps any failure of that crawl — unreadable directories, permission errors, or internal crawl failures — as `failed to crawl for stats: <cause>`. The actionable detail is always in the wrapped cause.
Source
Thrown at internal/cmd/stats.go:151
type ProjectStats struct {
ProjectPath string `json:"project_path"`
Stats *Stats `json:"stats"`
}
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()
}
View on GitHub (pinned to 7944b8e522)
Solutions
- Read the wrapped cause after the colon to see which path/operation failed.
- Verify the --crawl-dir path exists and is a directory: `ls -ld <dir>`.
- Check read/execute permissions on the directory tree (`find <dir> -not -readable`).
- Re-run pointing at a valid, accessible directory, or omit --crawl-dir to use the default local data directory.
Example fix
// before crush stats --crawl-dir ./projct # typo // after crush stats --crawl-dir ./project
Defensive patterns
Strategy: validation
Validate before calling
dir := "./project"
info, err := os.Stat(dir)
if err != nil || !info.IsDir() {
log.Fatalf("--crawl-dir %s is not an existing directory", dir)
}
if f, err := os.Open(dir); err != nil {
log.Fatalf("--crawl-dir %s not readable: %v", dir, err)
} else {
f.Close()
} Type guard
func isCrawlableDir(path string) bool {
info, err := os.Stat(path)
return err == nil && info.IsDir()
} Try / catch
out, err := exec.Command("crush", "stats", "--crawl-dir", dir).CombinedOutput()
if err != nil {
if strings.Contains(string(out), "failed to crawl for stats") {
log.Fatalf("crawl failed for %s: %s", dir, out)
}
log.Fatalf("stats failed: %v: %s", err, out)
} Prevention
- Verify the --crawl-dir path exists and is a directory before invoking.
- Use absolute paths to avoid cwd-related typos.
- Check permissions across the tree when crawling shared or system directories.
- Avoid crawling network mounts that can drop mid-scan; copy locally first if needed.
When it happens
Trigger: Running `crush stats` with a non-empty `--crawl-dir` flag where `crawlForStats(ctx, crawlDir)` at internal/cmd/stats.go:149 returns an error: the directory does not exist, is not readable, or the walker hits an unrecoverable I/O error while traversing.
Common situations: Typo in the --crawl-dir path; pointing at a file instead of a directory; crawling a directory with restricted permissions (e.g. another user's home); crawling a network mount that drops mid-scan.
Related errors
- failed to gather stats from projects: %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/c4f7e1962344f010.
Report an issue: GitHub.