plandex-ai/plandex · error
error reading settings file: %v
Error message
error reading settings file: %v
What it means
GetPlanSettings reads a plan's settings file from disk; when the file exists but cannot be read (I/O error other than not-exists), the read error is wrapped with this message. It signals a filesystem-level failure, not a missing-settings condition — a missing file returns a default PlanSettings instead.
Source
Thrown at app/server/db/settings_helpers.go:58
return nil, fmt.Errorf("error getting org default settings: %v", err)
}
if defaultSettings != nil {
log.Printf("GetPlanSettings - found org default settings for plan %s", plan.Id)
return defaultSettings, nil
} else {
log.Printf("GetPlanSettings - no org default settings found for plan %s", plan.Id)
}
log.Println("GetPlanSettings - no default settings found, returning default settings object")
// if it doesn't exist, return default settings object
settings = &shared.PlanSettings{
UpdatedAt: plan.CreatedAt,
ModelPackName: shared.DefaultModelPack.Name,
}
return settings, nil
} else if err != nil {
return nil, fmt.Errorf("error reading settings file: %v", err)
}
log.Printf("GetPlanSettings - settings found in file")
err = json.Unmarshal(bytes, &settings)
if err != nil {
return nil, fmt.Errorf("error unmarshalling settings: %v", err)
}
return settings, nil
}
func StorePlanSettings(plan *Plan, settings shared.PlanSettings) error {
planDir := getPlanDir(plan.OrgId, plan.Id)
settingsPath := filepath.Join(planDir, "settings.json")
settings.UpdatedAt = time.Now()View on GitHub (pinned to e2d772072e)
Solutions
- Check file permissions/ownership on the plan settings file and fix with chown/chmod so the server process can read it
- Verify the settings file path is a regular file, not a directory or symlink to a missing target
- Log the wrapped underlying error (%v of err) to identify the exact syscall failure
- If on a mounted volume, confirm the mount is healthy and the file exists
- Delete or restore the corrupted settings file so a fresh default is written
Example fix
// before
return nil, fmt.Errorf("error reading settings file: %v", err)
// after
return nil, fmt.Errorf("error reading settings file %s: %w", settingsPath, err) // include path + %w for unwrapping Defensive patterns
Strategy: fallback
Validate before calling
// before calling
if _, err := os.Stat(settingsPath); err != nil {
if os.IsNotExist(err) { return defaultPlanSettings(), nil } // missing file is fine
// permission or other I/O problem surfaces here
} Try / catch
settings, err := GetPlanSettings(ctx, plan)
if err != nil {
log.Printf("settings read failed: %v — falling back to defaults", err)
settings = &shared.PlanSettings{UpdatedAt: plan.CreatedAt, ModelPackName: shared.DefaultModelPack.Name}
} Prevention
- Treat not-exist as a normal case (defaults) and only surface real I/O errors
- Run the server with a filesystem it owns (consistent uid across deploys)
- Avoid writing settings files non-atomically; use temp file + rename
- Monitor wrapped errors for permission-denied patterns
When it happens
Trigger: os.ReadFile on the plan settings file returns an error other than os.IsNotExist — e.g. permission denied, path is a directory, or transient I/O failure while GetPlanSettings is called via LoadContexts, UpdateContexts, loadContexts, TellPlanHandler, or BuildPlanHandler.
Common situations: Settings file created by a different user/uid (permission mismatch after running app under another account), settings file corrupted by concurrent writers leaving it unreadable, or container volume mount issues.
Related errors
- error reading settings-v2.json: %v
- failed to seek in temporary file: %w
- error reading convo dir: %v
- error reading convo file: %v
- error reading convo message: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/9b7bf35c8cedaaa1.
Report an issue: GitHub.