{"record":{"id":"8dafaf0b8859d8af","repo":"Hmbown/CodeWhale","slug":"failed-to-serialize-mcp-config-e","errorCode":null,"errorMessage":"Failed to serialize MCP config: {e}","messagePattern":"Failed to serialize MCP config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":10321,"sourceCode":"                .all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.'))\n    };\n    valid_name(scope)\n        && valid_name(package)\n        && version.is_none_or(|value| {\n            !value.is_empty()\n                && !value.contains(['@', '/', '\\\\'])\n                && !value.chars().any(char::is_whitespace)\n        })\n}\n\nfn save_mcp_config(path: &Path, cfg: &McpConfig) -> Result<()> {\n    if let Some(parent) = path.parent() {\n        std::fs::create_dir_all(parent).with_context(|| {\n            format!(\"Failed to create MCP config directory {}\", parent.display())\n        })?;\n    }\n    let rendered = serde_json::to_string_pretty(cfg)\n        .map_err(|e| anyhow!(\"Failed to serialize MCP config: {e}\"))?;\n    crate::utils::write_atomic(path, rendered.as_bytes())\n        .map_err(|e| anyhow!(\"Failed to write MCP config {}: {}\", path.display(), e))?;\n    Ok(())\n}\n\nfn run_sandbox_command(args: SandboxArgs) -> Result<()> {\n    use crate::sandbox::{CommandSpec, SandboxManager};\n\n    let SandboxCommand::Run {\n        policy,\n        network,\n        writable_root,\n        exclude_tmpdir,\n        exclude_slash_tmp,\n        cwd,\n        timeout_ms,\n        command,\n    } = args.command;","sourceCodeStart":10303,"sourceCodeEnd":10339,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/lib.rs#L10303-L10339","documentation":"Thrown by the MCP config save routine when `serde_json::to_string_pretty(cfg)` fails to serialize the in-memory McpConfig back to JSON. This indicates a serialization-incompatible value in the config struct rather than a disk problem.","triggerScenarios":"Calling save_mcp_config (e.g. after mcp add/enable/disable) when serde cannot serialize the config — typically a map key type serde cannot render, or a custom/invalid value that serde_json refuses (e.g. non-string map keys like a PathBuf/integer key in a struct field), rather than plain struct data.","commonSituations":"A config built programmatically with unusual key types; version skew where a struct field was populated with a value its serde impl rejects; bugs in third-party tooling that edits the in-memory config before save.","solutions":["Inspect the wrapped serde error to find the field/key that fails to serialize.","Ensure map keys in McpConfig are String (JSON object keys must be strings).","Round-trip the config through load (which validates schema) before save instead of constructing it ad hoc.","If it persists, report it — this usually signals an internal bug, since CLI-populated configs are always JSON-serializable."],"exampleFix":"// before\ncfg.servers.insert(some_pathbuf, server); // non-string key\n// after\ncfg.servers.insert(some_pathbuf.to_string_lossy().to_string(), server);","handlingStrategy":"try-catch","validationCode":"serde_json::to_value(&cfg).map_err(|e| eprintln!(\"config not serializable: {e}\"))?; // probe before writing","typeGuard":null,"tryCatchPattern":"match serde_json::to_string_pretty(&cfg) {\n    Ok(s) => /* write s */,\n    Err(e) => eprintln!(\"serialize failed: {e}; config was not saved, original file untouched\"),\n}","preventionTips":["Keep all McpConfig map keys as String.","Round-trip configs through load() rather than constructing them ad hoc.","Treat this error as an internal bug and report it with the serde message."],"tags":["json","serialization","mcp","config"],"backgroundTag":"json-serialization-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}