Hmbown/CodeWhale · error · anyhow::Error
Failed to parse MCP config
Error message
Failed to parse MCP config {}; file contents were omitted What it means
load_config validates the path, reads mcp config JSON, and parses it. On a JSON syntax error the message reports the path but deliberately omits file contents (to avoid leaking secrets like API keys in MCP configs into logs/UI). The underlying serde error detail is also discarded.
Solutions
- Validate the file with a JSON parser/linter and fix the syntax error (note: comments are not allowed)
- Restore the file from backup or delete it to fall back to McpConfig::default()
- If you need the actual serde error detail, temporarily parse the file yourself with serde_json to see the line/column
Example fix
// before (broken)
{ "mcpServers": { "fs": { "command": "npx", } } }
// after
{ "mcpServers": { "fs": { "command": "npx" } } } Defensive patterns
Strategy: validation
Validate before calling
// validate before calling load_config
let text = std::fs::read_to_string(path)?;
serde_json::from_str::<serde_json::Value>(&text)
.map_err(|e| anyhow!("{}: invalid JSON at {}:{}", path.display(), e.line(), e.column()))?; Try / catch
match load_config(path) {
Err(e) if e.to_string().contains("Failed to parse MCP config") => {
prompt_user_to_fix_json(path); // e.g. run `jq . <file>` to locate the error
}
other => other,
} Prevention
- Run `jq . mcp.json` (or a linter) after hand-editing the config
- Never put comments or trailing commas in .json files
- Write configs atomically (temp file + rename) to avoid truncation
When it happens
Trigger: Loading an MCP config file whose contents are not valid JSON (trailing comma, comments, truncated file, wrong encoding).
Common situations: Hand-editing mcp.json and leaving a syntax error; a tool writing JSONC-style comments into a .json file; interrupted write leaving a truncated file.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse MCP config
- Failed to parse MCP config; file contents were omitted
- Failed to serialize MCP config
- invalid JSON payload at key
- invalid MCP server definition list in key
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ecaedb6f02a8adb9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp.rs:5326
// A server that is enabled, inspected, connected and erroring on
// nothing needs no recovery. It used to be labelled `diagnose`, so
// every healthy row advertised a repair it did not need — founder
// live-test: "even the ones that are connected say diagnose lol".
return None;
}
if oauth_capable {
return Some(McpRecoveryKind::Reauth);
}
Some(McpRecoveryKind::Reconnect)
}
pub fn load_config(path: &Path) -> Result<McpConfig> {
validate_mcp_config_path(path)?;
let Some(contents) = read_mcp_config_file(path)? else {
return Ok(McpConfig::default());
};
serde_json::from_str(&contents).map_err(|_| {
anyhow::anyhow!(
"Failed to parse MCP config {}; file contents were omitted",
codewhale_config::quote_os_path(path)
)
})
}
/// Maximum bytes read from an MCP config file. Configs are kilobytes.
const MAX_MCP_CONFIG_BYTES: u64 = 1024 * 1024;
fn read_mcp_config_file(path: &Path) -> Result<Option<String>> {
let metadata = match fs::symlink_metadata(path) {
Ok(metadata) => metadata,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(err) => {
return Err(err)
.with_context(|| format!("Failed to inspect MCP config {}", path.display()));
}
};View on GitHub (pinned to 73e0f67d83)