{"record":{"id":"33635152ffa7268f","repo":"Hmbown/CodeWhale","slug":"mcp-config-exceeds-the-1-mib-limit","errorCode":null,"errorMessage":"MCP config {} exceeds the 1 MiB limit","messagePattern":"MCP config (.+?) exceeds the 1 MiB limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/mcp.rs","lineNumber":5357,"sourceCode":"        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    };\n    let file_type = metadata.file_type();\n    if file_type.is_symlink() || !file_type.is_file() {\n        anyhow::bail!(\"MCP config path must be a regular file: {}\", path.display());\n    }\n\n    let file = open_mcp_config_file(path)\n        .with_context(|| format!(\"Failed to read MCP config {}\", path.display()))?;\n    let mut contents = String::new();\n    file.take(MAX_MCP_CONFIG_BYTES + 1)\n        .read_to_string(&mut contents)\n        .with_context(|| format!(\"Failed to read MCP config {}\", path.display()))?;\n    if contents.len() as u64 > MAX_MCP_CONFIG_BYTES {\n        anyhow::bail!(\"MCP config {} exceeds the 1 MiB limit\", path.display());\n    }\n    Ok(Some(contents))\n}\n\n#[cfg(unix)]\nfn open_mcp_config_file(path: &Path) -> std::io::Result<fs::File> {\n    use std::os::unix::fs::OpenOptionsExt;\n\n    fs::OpenOptions::new()\n        .read(true)\n        .custom_flags(libc::O_NOFOLLOW)\n        .open(path)\n}\n\n#[cfg(not(unix))]\nfn open_mcp_config_file(path: &Path) -> std::io::Result<fs::File> {\n    fs::File::open(path)\n}","sourceCodeStart":5339,"sourceCodeEnd":5375,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp.rs#L5339-L5375","documentation":"The MCP config file is read with a hard cap of MAX_MCP_CONFIG_BYTES (1 MiB); anything larger is rejected before parsing. This bounds memory use and protects against pathological or hostile config files.","triggerScenarios":"Calling the MCP config loader with a file whose contents.len() > 1 MiB (read via file.take(MAX + 1) to detect oversize).","commonSituations":"An MCP config that accumulated hundreds of server entries or embedded credentials/blobs; a merge tool duplicating entries; accidentally pointing the loader at a large log or data file.","solutions":["Trim the config: remove unused servers, disabled tools, and duplicated entries","Move large blobs (certs, data) out of the config into referenced files","Verify the path points at the intended MCP config, not a log or dump file"],"exampleFix":"// before\n{ \"mcpServers\": { ...1200 entries incl. inline certs... } } // 1.4 MiB\n// after\n{ \"mcpServers\": { ...only active servers... } } // < 1 MiB; certs moved to files","handlingStrategy":"validation","validationCode":"let size = std::fs::metadata(path)?.len();\nif size > 1024 * 1024 {\n    return Err(format!(\"{path:?} exceeds the 1 MiB MCP config limit\"));\n}","typeGuard":null,"tryCatchPattern":"match load_mcp_config(path) {\n    Err(e) if e.to_string().contains(\"1 MiB limit\") => {\n        eprintln!(\"trim {path:?} to under 1 MiB before loading\");\n    }\n    other => other?,\n}","preventionTips":["Keep MCP configs to active servers only; prune stale entries periodically","Never inline large blobs (certs, datasets) into the config","Check file size with fs::metadata before loading configs from untrusted sources"],"tags":["mcp","config","size-limit"],"backgroundTag":"file-size-limit-exceeded","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"}