charmbracelet/crush · error
failed to reload config: %w
Error message
failed to reload config: %w
What it means
reloadFromDiskLocked calls loadFromConfigPaths then loadFromConfigPaths-merged loading of crushrc/crush.json files; if parsing/merging of the discovered config files fails, the error is wrapped as 'failed to reload config'. The store rolls back to its previous state.
Source
Thrown at internal/config/store.go:1183
// Concurrent calls are serialised via writeMu.
func (s *ConfigStore) ReloadFromDisk(ctx context.Context) error {
if s.workingDir == "" {
return fmt.Errorf("cannot reload: working directory not set")
}
s.writeMu.Lock()
defer s.writeMu.Unlock()
return s.reloadFromDiskLocked(ctx)
}
// reloadFromDiskLocked performs the actual reload. Caller must hold writeMu.
func (s *ConfigStore) reloadFromDiskLocked(ctx context.Context) error {
// Migrate deprecated disable_notifications before reloading config.
migrateDisableNotifications()
configPaths := lookupConfigs(s.workingDir)
cfg, loadedPaths, err := loadFromConfigPaths(ctx, configPaths)
if err != nil {
return fmt.Errorf("failed to reload config: %w", err)
}
// Apply defaults (using existing data directory if set)
var dataDir string
if cur := s.Config(); cur != nil && cur.Options != nil {
dataDir = cur.Options.DataDirectory
}
cfg.setDefaults(s.workingDir, dataDir)
// Merge workspace config if present
workspacePath := filepath.Join(cfg.Options.DataDirectory, fmt.Sprintf("%s.json", appName))
if wsData, err := os.ReadFile(workspacePath); err == nil && len(wsData) > 0 {
if !json.Valid(wsData) {
return fmt.Errorf("invalid JSON in config file %s", workspacePath)
}
merged, mergeErr := loadFromBytes(append([][]byte{mustMarshalConfig(cfg)}, wsData))
if mergeErr == nil {
dataDir := cfg.Options.DataDirectoryView on GitHub (pinned to 7944b8e522)
Solutions
- Validate the JSON (jq . crush.json) or bash syntax (bash -n crushrc) in the files listed by lookupConfigs for the working directory.
- Fix the syntax error at the reported position and reload again.
- Temporarily move the offending config file aside to confirm it is the culprit, then fix and restore.
- Check file permissions are readable by the process.
Example fix
// before: broken crush.json
{"providers": "oops"}
// after
{"providers": {"anthropic": {"api_key": "sk-..."}}} Defensive patterns
Strategy: validation
Validate before calling
for _, p := range configPaths { if strings.HasSuffix(p, ".json") { b, _ := os.ReadFile(p); if len(b) > 0 && !json.Valid(b) { return fmt.Errorf("invalid JSON: %s", p) } } } Try / catch
if err := store.ReloadFromDisk(ctx); err != nil {
var cfgErr *ConfigLoadError
if errors.As(err, &cfgErr) { openEditor(cfgErr.Path) }
} Prevention
- Lint crush.json/crushrc in CI or an editor hook
- bash -n your crushrc before saving
- Keep config files under version control to diff mistakes
When it happens
Trigger: loadFromConfigPaths(ctx, configPaths) returns an error: malformed crushrc script or crush.json (invalid JSON, bad bash syntax in shell config), unreadable file, or a merge conflict in config structure.
Common situations: User just edited crush.json and left a syntax error; a crushrc with a failing command; permissions changed on a config file mid-session.
Related errors
- cannot reload: working directory not set
- invalid JSON in config file %s
- failed to load providers during reload: %w
- requested channels differ from the existing workspace; chann
- could not create request: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/c05db38510f8e970.
Report an issue: GitHub.