Hmbown/CodeWhale · error
Failed to parse config file
Error message
Failed to parse config file {}; file contents were omitted What it means
Thrown by `load_single_config_file` when a config file reads fine but `toml::from_str::<ConfigFile>` cannot parse it. The path is quoted via `quote_os_path` and, per the codebase-wide convention, the file contents and offending keys are omitted from the message because configs may contain secrets.
Solutions
- Run the file through a TOML linter/validator and fix the reported syntax error
- Search the file for merge-conflict markers and stray characters, then remove them
- Restore the file from version control or back it up and let the app regenerate defaults
Example fix
// before <<<<<<< HEAD model = "a" ======= model = "b" >>>>>>> main // after model = "b"
Defensive patterns
Strategy: try-catch
Validate before calling
let contents = std::fs::read_to_string(&path)?;
contents.parse::<toml::Value>().map_err(|e| anyhow!("config file {} TOML invalid: {e}", path.display()))?; Try / catch
match load_single_config_file(&path) {
Ok(cfg) => cfg,
Err(e) if e.to_string().contains("Failed to parse config file") => {
eprintln!("Check TOML syntax in {} (contents omitted from the error)", path.display());
Config::default()
}
Err(e) => return Err(e),
} Prevention
- Resolve merge conflicts in config files completely — search for conflict markers before launching
- Run a TOML formatter/linter on config files in CI
- Avoid editing configs with editors that insert smart quotes
When it happens
Trigger: Calling `load_single_config_file(path)` on a config file whose TOML syntax or schema is invalid; the distinct 'Failed to read config file' error covers unreadable files, this one covers unparseable content.
Common situations: A merge conflict marker (`<<<<<<<`) left in config.toml; trailing text after a table; a key duplicated within the same table after hand-merging settings; editing on Windows and pasting a smart quote.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Could not parse configuration for route preference…
- Could not parse destination route identity; contents omitted
- failed to parse config at
- failed to parse config at
- failed to parse config at
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/afd94df6a23e1342.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/config.rs:11543
),
modelstudio_coding_plan: merge_provider_config(
base.modelstudio_coding_plan,
override_cfg.modelstudio_coding_plan,
),
modelstudio_coding_plan_anthropic: merge_provider_config(
base.modelstudio_coding_plan_anthropic,
override_cfg.modelstudio_coding_plan_anthropic,
),
custom: merge_custom_providers(base.custom, override_cfg.custom),
}),
}
}
fn load_single_config_file(path: &Path) -> Result<Config> {
let contents = fs::read_to_string(path)
.with_context(|| format!("Failed to read config file: {}", path.display()))?;
let parsed: ConfigFile = toml::from_str(&contents).map_err(|_| {
anyhow::anyhow!(
"Failed to parse config file {}; file contents were omitted",
codewhale_config::quote_os_path(path)
)
})?;
Ok(*parsed.base)
}
/// Build a one-line warning when top-level-only keys are nested under a section
/// Codewhale does not define (`[general]` / `[sandbox]`). TOML silently drops
/// those keys, so e.g. `[general]\nallow_shell = true` never takes effect and
/// the shell tools (`exec_shell`, `task_shell_start`, …) are absent from the
/// catalog with no explanation. Returns `None` when nothing is misplaced.
///
/// This is the exact confusion behind #2589: `allow_shell` and `sandbox_mode`
/// belong at the top of the file, above any `[section]` header.
fn warn_on_misplaced_top_level_keys(raw: &str) -> Option<String> {
let doc = toml::from_str::<toml::Value>(raw).ok()?;
// Sections Codewhale does not recognize but users nest settings under.View on GitHub (pinned to 73e0f67d83)