Hmbown/CodeWhale · error
Failed to read MCP config
Error message
Failed to read MCP config {}: {} What it means
Thrown by `load_mcp_config` when the config file exists but cannot be read from disk (permissions, I/O error). The path and the underlying io::Error are included in the message. A non-existent path is not an error — it returns a default config.
Solutions
- Fix permissions on the config file (e.g. `chmod u+rw <path>` or chown to your user).
- Confirm the path is a regular file, not a directory (`ls -l <path>`).
- If it was created by root/sudo, chown it back to your user or recreate it as your user.
- Check the wrapped OS error for the underlying cause (EACCES, EISDIR, EIO) and address it directly.
Example fix
// before sudo codewhale mcp add myserver -- cmd # creates root-owned config // after codewhale mcp add myserver -- cmd sudo chown $USER ~/.config/codewhale/mcp.json # repair if needed
Defensive patterns
Strategy: try-catch
Validate before calling
let meta = std::fs::metadata(&path)?;
if !meta.is_file() { eprintln!("config path is not a regular file: {}", path.display()); }
let f = std::fs::OpenOptions::new().read(true).open(&path)?; // probe readability Try / catch
match std::fs::read_to_string(&path) {
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => eprintln!("fix ownership/permissions on {}", path.display()),
Err(e) => eprintln!("read failed: {e}"),
Ok(_) => /* continue */,
} Prevention
- Never run MCP CLI commands under sudo; repair ownership with chown instead.
- Keep config files as regular files with user-owned permissions (0600).
- Check `ls -l` on the config path when hitting read errors.
When it happens
Trigger: Any `codewhale mcp` subcommand that calls load_mcp_config when `std::fs::read_to_string(path)` fails: file exists but lacks read permission, path is a directory, or an OS-level I/O error occurs.
Common situations: Config file owned by another user or written by root; restrictive umask after running as a different user; the path points at a directory; disk/network filesystem errors; Windows file locking.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Failed to write MCP config
- MCP config path must be a regular file
- agent profile tools.posture= would widen permissions; use…
- Android loaded image
- Cannot resolve current binary path
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/229340faf25b669a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/lib.rs:10123
println!(" command: {exe_str}");
println!(
" args: {}serve --mcp",
workspace.map_or(String::new(), |ws| format!("--workspace {ws} "))
);
println!();
println!("Tip: Use `codewhale mcp validate` to test the connection.");
println!(" Use `codewhale serve --http` for the HTTP/SSE runtime API instead.");
Ok(())
}
}
}
fn load_mcp_config(path: &Path) -> Result<McpConfig> {
if !path.exists() {
return Ok(McpConfig::default());
}
let contents = std::fs::read_to_string(path)
.map_err(|e| anyhow::anyhow!("Failed to read MCP config {}: {}", path.display(), e))?;
let cfg: McpConfig = serde_json::from_str(&contents).map_err(|_| {
anyhow::anyhow!(
"Failed to parse MCP config {}; file contents were omitted",
codewhale_config::quote_os_path(path)
)
})?;
Ok(cfg)
}
/// Diagnostic status for an MCP server entry.
#[derive(Debug)]
enum McpServerDoctorStatus {
Ok(String),
Warning(String),
Error(String),
}
impl McpServerDoctorStatus {View on GitHub (pinned to 433685b202)