Hmbown/CodeWhale · warning · anyhow::Error

invalid MCP server definition list in key {MCP_SERVER_DEFINI

Error message

invalid MCP server definition list in key {MCP_SERVER_DEFINITIONS_KEY}; contents were omitted

What it means

The value at mcp.server_definitions parsed as a JSON string (the legacy double-encoded shape) but the inner payload is not a Vec<McpServerDefinition> — wrong top-level type or definitions missing/renaming required fields. Contents are omitted from the message; the load path downgrades it to a warning with an empty server list.

Source

Thrown at crates/cli/src/lib.rs:4367

        Err(err) => {
            eprintln!(
                "warning: failed to parse persisted MCP server definitions ({MCP_SERVER_DEFINITIONS_KEY}): {err}"
            );
            Vec::new()
        }
    }
}

fn parse_mcp_server_definitions(raw: &str) -> Result<Vec<McpServerDefinition>> {
    if let Ok(parsed) = serde_json::from_str::<Vec<McpServerDefinition>>(raw) {
        return Ok(parsed);
    }

    let unwrapped: String = serde_json::from_str(raw).map_err(|_| {
        anyhow!("invalid JSON payload at key {MCP_SERVER_DEFINITIONS_KEY}; contents were omitted")
    })?;
    serde_json::from_str::<Vec<McpServerDefinition>>(&unwrapped).map_err(|_| {
        anyhow!(
            "invalid MCP server definition list in key {MCP_SERVER_DEFINITIONS_KEY}; contents were omitted"
        )
    })
}

fn persist_mcp_server_definitions(
    store: &mut ConfigStore,
    definitions: &[McpServerDefinition],
) -> Result<()> {
    let encoded =
        serde_json::to_string(definitions).context("failed to encode MCP server definitions")?;
    store
        .config
        .set_value(MCP_SERVER_DEFINITIONS_KEY, &encoded)?;
    store.save()
}

/// Delegate a long-running server command (`serve --http`/`--mobile`,

View on GitHub (pinned to 8880682c63)

Solutions

  1. Delete the key and re-register the servers with the current CLI version so it persists the current schema
  2. Or fix the inner JSON to match the current definition schema (verify field names against the version in use)
  3. Prefer managing definitions through the CLI's mcp commands rather than by hand
Defensive patterns

Strategy: type-guard

Type guard

fn is_valid_definition_list(raw: &str) -> bool {
    let inner: serde_json::Value = match serde_json::from_str(raw) {
        Ok(v) => v,
        Err(_) => return false,
    };
    inner.as_array().is_some_and(|items| {
        items.iter().all(|item| item.is_object() && item.get("command").is_some_and(serde_json::Value::is_string))
    })
}

Prevention

When it happens

Trigger: A double-encoded string whose inner JSON is an object instead of an array, or an array whose elements fail the current McpServerDefinition schema (e.g. field renames between CLI versions).

Common situations: Old-version persisted payloads read by a newer CLI after a schema change; hand-crafted definitions guessing at field names.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/20015a790d9d5f1e. Report an issue: GitHub.