charmbracelet/crush · error
failed to load shell config %s: %w
Error message
failed to load shell config %s: %w
What it means
When a candidate config path is a shell config (crushrc), loadFromConfigPaths runs it through shellconfig.LoadShellConfig to produce JSON. Any error executing/evaluating the bash-based config is wrapped with this message and aborts config loading.
Source
Thrown at internal/config/load.go:996
if path == "" {
continue
}
data, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
continue
}
return nil, nil, fmt.Errorf("failed to open config file %s: %w", path, err)
}
if len(data) == 0 {
continue
}
dir := filepath.Dir(path)
if isShellConfig(path) {
jsonBytes, err := shellconfig.LoadShellConfig(ctx, path, data)
if err != nil {
return nil, nil, fmt.Errorf("failed to load shell config %s: %w", path, err)
}
if len(jsonBytes) > 0 {
if !json.Valid(jsonBytes) {
return nil, nil, fmt.Errorf("shell config %s produced invalid JSON", path)
}
addTopLevelKeys(shDirKeys, dir, jsonBytes)
configs = append(configs, jsonBytes)
loaded = append(loaded, path)
}
} else {
if !json.Valid(data) {
return nil, nil, fmt.Errorf("invalid JSON in config file %s", path)
}
addTopLevelKeys(jsonDirKeys, dir, data)
configs = append(configs, data)
loaded = append(loaded, path)
}
}View on GitHub (pinned to 7944b8e522)
Solutions
- Run bash -n on your crushrc to catch syntax errors before starting
- Check the inner error after the colon — it names the failing line/command in the shell config
- Simplify the crushrc: comment out blocks and re-add until the failing one is found
- Verify builtin usage (provider, model, mcp, lsp, permissions, hook, options) matches the documented syntax
Example fix
# before (crushrc)
provider anthropic {
api_key $ANTHROPIC_API_KEY
# missing closing brace
# after
provider anthropic {
api_key $ANTHROPIC_API_KEY
} Defensive patterns
Strategy: validation
Validate before calling
// syntax-check a crushrc before load
if out, err := exec.Command("bash", "-n", crushrcPath).CombinedOutput(); err != nil {
return fmt.Errorf("crushrc syntax error: %s: %w", out, err)
} Try / catch
cfg, err := config.Load(ctx, ...)
if err != nil && strings.Contains(err.Error(), "failed to load shell config") {
// surface the inner bash error line to the user, do not retry blindly
} Prevention
- Run bash -n on crushrc in CI
- Quote all variable expansions in crushrc
- Keep builtin calls to documented builtins only
When it happens
Trigger: Load reads a crushrc file, isShellConfig(path) is true, and shellconfig.LoadShellConfig fails: bash syntax error, unknown builtin, failing command substitution, or the ConfigBuilder gate rejects a builtin call.
Common situations: Bash typo or unbalanced quotes in crushrc; referencing an undefined variable at config-eval time; a builtin like provider/mcp called with wrong arguments; running in an environment where the embedded bash cannot execute.
Related errors
- shell config %s produced invalid JSON
- task agent not configured
- small model provider not configured
- coder agent not configured
- model provider not configured
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/98f84dd3c36843e8.
Report an issue: GitHub.