Hmbown/CodeWhale · error · McpManagementFailure

{error}

Error message

{error}

What it means

This error carries the underlying MCP configuration mutation failure, wrapped in McpManagementFailure and surfaced through mcp_mutation_error. The write runs inside spawn_blocking under the config write lock; if the closure returns an error, its Display text becomes the message. The ApiError::internal('MCP configuration write failed') variant applies only when the blocking task itself panicked or was cancelled.

Solutions

  1. Read the embedded {error} text to identify the underlying cause and fix that first.
  2. Validate the MCP config file parses as the expected schema; fix or regenerate it.
  3. Check the mcp_config_path is writable by the process.
  4. If the task panicked, inspect the panic message; the generic 'MCP configuration write failed' means the closure never returned.

Example fix

// before: hand-edited config with duplicate server key
{"mcpServers": {"fs": {...}, "fs": {...}}}
// after: unique keys, valid JSON
{"mcpServers": {"fs": {...}, "git": {...}}}
Defensive patterns

Strategy: try-catch

Validate before calling

let raw = std::fs::read_to_string(state.config.read().mcp_config_path())?;
serde_json::from_str::<codewhale_config::Config>(&raw).map_err(|e| format!("mcp config invalid: {e}"))?;

Try / catch

match api.mutate_mcp_config(...).await { Err(ApiError::Message(msg)) => eprintln!("mcp write failed: {msg}"), Err(e) => eprintln!("task failure: {e}"), Ok(v) => v }

Prevention

When it happens

Trigger: Calling the runtime API MCP config mutate endpoint (crates/tui/src/runtime_api.rs:4187) when crate::mcp::mutate_config fails: unreadable/corrupt mcp config file, serialization failure, or the mutate closure rejecting the change (e.g. duplicate server id).

Common situations: MCP config file hand-edited into invalid JSON; config path pointing somewhere unwritable; adding an MCP server that already exists; concurrent API calls racing on the same config.

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@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/8ef2cb682ca71da3. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_api.rs:4187

    Ok(value.to_owned())
}

async fn mutate_mcp_management<T: Send + 'static>(
    state: RuntimeApiState,
    headers: axum::http::HeaderMap,
    mutate: impl FnOnce(&RuntimeApiState, &mut crate::mcp::McpConfig) -> Result<T, ApiError>
    + Send
    + 'static,
) -> Result<(T, String), ApiError> {
    let expected = mcp_expected_revision(&headers)?;
    #[cfg(test)]
    let env_ticket = crate::test_support::env_scope_ticket();
    tokio::task::spawn_blocking(move || {
        #[cfg(test)]
        let _membership = crate::test_support::join_env_scope(env_ticket);
        let path = state.config.read().mcp_config_path();
        crate::mcp::mutate_config(&path, Some(&expected), |config| {
            mutate(&state, config).map_err(|error| anyhow::Error::new(McpManagementFailure(error)))
        })
        .map_err(mcp_mutation_error)
    })
    .await
    .map_err(|_| ApiError::internal("MCP configuration write failed"))?
}

async fn mcp_management_snapshot(
    state: RuntimeApiState,
) -> Result<
    (
        (
            crate::mcp::McpConfig,
            std::collections::HashMap<String, &'static str>,
        ),
        String,
    ),
    ApiError,

View on GitHub (pinned to 73e0f67d83)