Hmbown/CodeWhale · error

Failed to write MCP config

Error message

Failed to write MCP config {}: {}

What it means

Thrown by the MCP config save routine when creating the serialized JSON succeeded but the atomic write to disk failed. The message includes the target path and the underlying error from `crate::utils::write_atomic`.

Solutions

  1. Fix permissions: ensure your user can write the config file and its parent directory.
  2. Free disk space or resolve quota limits if the wrapped error indicates ENOSPC.
  3. Check whether the filesystem/mount is read-only and remount or choose another --config-path.
  4. Recreate a root-owned config as your user (`sudo chown $USER <path>`).

Example fix

// before
sudo codewhale mcp enable my-server   # may leave root-owned config
// after
codewhale mcp enable my-server
# or repair once: sudo chown $USER: $(path to mcp.json)
Defensive patterns

Strategy: try-catch

Validate before calling

let probe = path.with_extension(".probe");
if std::fs::write(&probe, b"").is_err() {
    eprintln!("no write access to config directory: {}", path.display());
}
let _ = std::fs::remove_file(&probe);

Try / catch

match std::fs::write(&path, &rendered) {
    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => eprintln!("chown/chmod the config: {}", path.display()),
    Err(e) => eprintln!("write failed: {e}"),
    Ok(_) => /* continue */,
}

Prevention

When it happens

Trigger: save_mcp_config when write_atomic fails: no write permission on the file or its directory, directory was removed between create_dir_all and the write, read-only filesystem, disk full, or (for atomic rename semantics) cross-device or lock issues on the target path.

Common situations: Config file owned by root after a sudo run; read-only mount or container filesystem; disk quota exceeded; another process holding a conflicting lock; antivirus/backup tools briefly locking the file on Windows.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

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

    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;

    let policy = parse_sandbox_policy(

View on GitHub (pinned to 433685b202)