{"record":{"id":"ecaedb6f02a8adb9","repo":"Hmbown/CodeWhale","slug":"failed-to-parse-mcp-config-file-contents-were-ecaedb","errorCode":null,"errorMessage":"Failed to parse MCP config {}; file contents were omitted","messagePattern":"Failed to parse MCP config (.+?); file contents were omitted","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":5326,"sourceCode":"        // A server that is enabled, inspected, connected and erroring on\n        // nothing needs no recovery. It used to be labelled `diagnose`, so\n        // every healthy row advertised a repair it did not need — founder\n        // live-test: \"even the ones that are connected say diagnose lol\".\n        return None;\n    }\n    if oauth_capable {\n        return Some(McpRecoveryKind::Reauth);\n    }\n    Some(McpRecoveryKind::Reconnect)\n}\n\npub fn load_config(path: &Path) -> Result<McpConfig> {\n    validate_mcp_config_path(path)?;\n    let Some(contents) = read_mcp_config_file(path)? else {\n        return Ok(McpConfig::default());\n    };\n    serde_json::from_str(&contents).map_err(|_| {\n        anyhow::anyhow!(\n            \"Failed to parse MCP config {}; file contents were omitted\",\n            codewhale_config::quote_os_path(path)\n        )\n    })\n}\n\n/// Maximum bytes read from an MCP config file. Configs are kilobytes.\nconst MAX_MCP_CONFIG_BYTES: u64 = 1024 * 1024;\n\nfn read_mcp_config_file(path: &Path) -> Result<Option<String>> {\n    let metadata = match fs::symlink_metadata(path) {\n        Ok(metadata) => metadata,\n        Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),\n        Err(err) => {\n            return Err(err)\n                .with_context(|| format!(\"Failed to inspect MCP config {}\", path.display()));\n        }\n    };","sourceCodeStart":5308,"sourceCodeEnd":5344,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp.rs#L5308-L5344","documentation":"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.","triggerScenarios":"Loading an MCP config file whose contents are not valid JSON (trailing comma, comments, truncated file, wrong encoding).","commonSituations":"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.","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"],"exampleFix":"// before (broken)\n{ \"mcpServers\": { \"fs\": { \"command\": \"npx\", } } }\n// after\n{ \"mcpServers\": { \"fs\": { \"command\": \"npx\" } } }","handlingStrategy":"validation","validationCode":"// validate before calling load_config\nlet text = std::fs::read_to_string(path)?;\nserde_json::from_str::<serde_json::Value>(&text)\n    .map_err(|e| anyhow!(\"{}: invalid JSON at {}:{}\", path.display(), e.line(), e.column()))?;","typeGuard":null,"tryCatchPattern":"match load_config(path) {\n    Err(e) if e.to_string().contains(\"Failed to parse MCP config\") => {\n        prompt_user_to_fix_json(path); // e.g. run `jq . <file>` to locate the error\n    }\n    other => other,\n}","preventionTips":["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"],"tags":["mcp","json","config","parse-error"],"backgroundTag":"json-parse-error","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}