{"record":{"id":"01222631fd0cefda","repo":"openai/codex","slug":"invaliddata-012226","errorCode":"InvalidData","errorMessage":"{}","messagePattern":"\\{\\}","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/config/src/mcp_edit.rs","lineNumber":20,"sourceCode":"use std::io::ErrorKind;\nuse std::path::Path;\n\nuse toml::Value as TomlValue;\n\nuse crate::CONFIG_TOML_FILE;\nuse crate::McpServerConfig;\n\npub async fn load_global_mcp_servers(\n    codex_home: &Path,\n) -> std::io::Result<BTreeMap<String, McpServerConfig>> {\n    let config_path = codex_home.join(CONFIG_TOML_FILE);\n    let raw = match tokio::fs::read_to_string(&config_path).await {\n        Ok(raw) => raw,\n        Err(err) if err.kind() == ErrorKind::NotFound => return Ok(BTreeMap::new()),\n        Err(err) => return Err(err),\n    };\n    let parsed = toml::from_str::<TomlValue>(&raw)\n        .map_err(|err| std::io::Error::new(ErrorKind::InvalidData, err))?;\n    let Some(servers_value) = parsed.get(\"mcp_servers\") else {\n        return Ok(BTreeMap::new());\n    };\n\n    ensure_no_inline_bearer_tokens(servers_value)?;\n\n    servers_value\n        .clone()\n        .try_into()\n        .map_err(|err| std::io::Error::new(ErrorKind::InvalidData, err))\n}\n\nfn ensure_no_inline_bearer_tokens(value: &TomlValue) -> std::io::Result<()> {\n    let Some(servers_table) = value.as_table() else {\n        return Ok(());\n    };\n\n    for (server_name, server_value) in servers_table {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/config/src/mcp_edit.rs#L2-L38","documentation":"load_global_mcp_servers reads $CODEX_HOME/config.toml directly (not through the layered config loader) and parses the whole file as a toml::Value. Any TOML syntax error anywhere — even outside [mcp_servers] — becomes io::Error(InvalidData) whose message is the raw toml parse error with line/column. A missing file returns an empty map, so this error always means 'the file exists but does not parse'.","triggerScenarios":"Awaiting load_global_mcp_servers with any syntax error in config.toml: an unterminated string in an unrelated section, duplicate keys, or a malformed inline table under mcp_servers.","commonSituations":"Hand-editing MCP config and breaking another section of the same file; snippets pasted in YAML/JSON shape; another tool appending malformed fragments to config.toml.","solutions":["Fix the syntax error at the reported line/column of config.toml","Pre-validate the file (taplo lint / python tomllib) before starting codex","Prefer `codex mcp add` so the file is edited structurally, not by hand"],"exampleFix":"# before\n[mcp_servers.search]\ncommand = \"npx\nargs = [\"-y\", \"some-server\"]\n\n# after — close the quote\n[mcp_servers.search]\ncommand = \"npx\"\nargs = [\"-y\", \"some-server\"]","handlingStrategy":"validation","validationCode":"use std::path::Path;\n\n// Run before load_global_mcp_servers.\nasync fn config_toml_parses(codex_home: &Path) -> std::io::Result<()> {\n    let raw = tokio::fs::read_to_string(codex_home.join(\"config.toml\")).await?;\n    toml::from_str::<toml::Value>(&raw)\n        .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match load_global_mcp_servers(codex_home).await {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData\n        && !e.to_string().contains(\"mcp_servers.\") => {\n        // Whole-file TOML syntax error; the message carries line/column.\n        // (InvalidData naming mcp_servers.<name> is a schema or token issue.)\n    }\n    Err(e) => return Err(e),\n    Ok(servers) => { /* ... */ }\n}","preventionTips":["Use `codex mcp add` / `codex mcp remove` instead of hand-editing the mcp_servers section","Parse-check config.toml with editor tooling (taplo, Even Better TOML) so syntax errors never reach runtime","Remember the whole file must parse — an error outside mcp_servers still breaks MCP loading"],"tags":["toml","mcp","config","parse-error","rust"],"backgroundTag":"toml-parse-error","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}