Hmbown/CodeWhale · error

Failed to serialize MCP config

Error message

Failed to serialize MCP config: {e}

What it means

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.

Solutions

  1. Inspect the wrapped serde error to find the field/key that fails to serialize.
  2. Ensure map keys in McpConfig are String (JSON object keys must be strings).
  3. Round-trip the config through load (which validates schema) before save instead of constructing it ad hoc.
  4. If it persists, report it — this usually signals an internal bug, since CLI-populated configs are always JSON-serializable.

Example fix

// before
cfg.servers.insert(some_pathbuf, server); // non-string key
// after
cfg.servers.insert(some_pathbuf.to_string_lossy().to_string(), server);
Defensive patterns

Strategy: try-catch

Validate before calling

serde_json::to_value(&cfg).map_err(|e| eprintln!("config not serializable: {e}"))?; // probe before writing

Try / catch

match serde_json::to_string_pretty(&cfg) {
    Ok(s) => /* write s */,
    Err(e) => eprintln!("serialize failed: {e}; config was not saved, original file untouched"),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/8dafaf0b8859d8af. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:10321

                .all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.'))
    };
    valid_name(scope)
        && valid_name(package)
        && version.is_none_or(|value| {
            !value.is_empty()
                && !value.contains(['@', '/', '\\'])
                && !value.chars().any(char::is_whitespace)
        })
}

fn save_mcp_config(path: &Path, cfg: &McpConfig) -> Result<()> {
    if let Some(parent) = path.parent() {
        std::fs::create_dir_all(parent).with_context(|| {
            format!("Failed to create MCP config directory {}", parent.display())
        })?;
    }
    let rendered = serde_json::to_string_pretty(cfg)
        .map_err(|e| anyhow!("Failed to serialize MCP config: {e}"))?;
    crate::utils::write_atomic(path, rendered.as_bytes())
        .map_err(|e| anyhow!("Failed to write MCP config {}: {}", path.display(), e))?;
    Ok(())
}

fn run_sandbox_command(args: SandboxArgs) -> Result<()> {
    use crate::sandbox::{CommandSpec, SandboxManager};

    let SandboxCommand::Run {
        policy,
        network,
        writable_root,
        exclude_tmpdir,
        exclude_slash_tmp,
        cwd,
        timeout_ms,
        command,
    } = args.command;

View on GitHub (pinned to 433685b202)