charmbracelet/crush · error
failed to load projects: %w
Error message
failed to load projects: %w
What it means
When `crush stats --all` is used, stats are gathered from every project listed in projects.json (next to the global config). This error wraps a failure from projects.Load(), which can only happen if projects.json exists but is unreadable or is not valid JSON.
Source
Thrown at internal/cmd/stats.go:317
"logs": true,
"generated": true,
"bower_components": true,
"jspm_packages": true,
".cache": true,
".npm": true,
".cargo": true,
"Library": true,
"Applications": true,
"System": true,
}
return skipDirs[name]
}
// gatherStatsFromProjects gathers stats from all known projects in projects.json.
func gatherStatsFromProjects(ctx context.Context) ([]ProjectStats, error) {
projectList, err := projects.Load()
if err != nil {
return nil, fmt.Errorf("failed to load projects: %w", err)
}
var dbPaths []struct {
dbPath string
projectDir string
}
for _, p := range projectList.Projects {
dbPath := filepath.Join(p.DataDir, "crush.db")
if _, err := os.Stat(dbPath); err == nil {
dbPaths = append(dbPaths, struct {
dbPath string
projectDir string
}{dbPath: dbPath, projectDir: p.Path})
}
}
return gatherStatsFromDBPaths(ctx, dbPaths)View on GitHub (pinned to 7944b8e522)
Solutions
- Validate the file: `cat $(dirname $(crush config path))/projects.json | jq .` — fix or remove broken JSON
- If the file is corrupt and not needed, delete it; projects.Load() recreates an empty list when it is absent
- Fix permissions on the file so the current user can read it (chown/chmod)
Example fix
// before (corrupt projects.json)
{"projects": [ {"path": "/a", // truncated
// after
rm projects.json # or repair with jq; Load() then returns an empty project list Defensive patterns
Strategy: validation
Validate before calling
pj="$(dirname "$(crush config path 2>/dev/null)")/projects.json" if [ -f "$pj" ] && ! jq empty "$pj" 2>/dev/null; then echo "projects.json is invalid JSON; repair or remove it: $pj" >&2 exit 1 fi
Try / catch
if err := runStats(...); err != nil {
var syntaxErr *json.SyntaxError
if errors.As(err, &syntaxErr) {
fmt.Fprintf(os.Stderr, "projects.json corrupt at offset %d; delete it to reset\n", syntaxErr.Offset)
return nil
}
return err
} Prevention
- Never hand-edit projects.json without validating with jq afterwards
- Avoid running crush with sudo, which can leave unreadable root-owned config files
- Back up the config directory before modifying it
- If stats --all fails on load, deleting projects.json is safe: Load returns an empty list when the file is missing
When it happens
Trigger: Running `crush stats` with the all-projects flag when projects.json cannot be read (permission denied) or json.Unmarshal fails because the file is malformed/hand-edited incorrectly.
Common situations: Manually editing ~/.config/crush/projects.json and breaking the JSON syntax; file owned by root after running crush with sudo once; disk corruption; truncation from an interrupted write.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- %s model: provider %q not found in configuration. Use 'crush
- %s model %q not found
- failed to get config: %w
- failed to load configuration: %v
- failed to tail log file: %v
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/9c1988812ae6a13a.
Report an issue: GitHub.