Hmbown/CodeWhale · error

invalid MCP server definition list in key

Error message

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

What it means

After unwrapping the raw value at MCP_SERVER_DEFINITIONS_KEY into a JSON string, parse_mcp_server_definitions still fails to deserialize it into Vec<McpServerDefinition>. The raw value was valid JSON (a string) but its contents are not an array of valid server definitions. Contents are omitted from the message to avoid leaking embedded secrets.

Solutions

  1. Check the McpServerDefinition struct in the CLI source for required fields and types and fix the JSON to match.
  2. Ensure the inner payload is an array: wrap a single definition object in `[...]`.
  3. Run `jq` against the unwrapped string to spot the schema mismatch.
  4. Upgrade or downgrade the CLI to the version matching your config schema.

Example fix

// before
"mcpServers": {"name": "fs"}
// after
"mcpServers": "[{\"name\":\"fs\",\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-fs\"]}]"
Defensive patterns

Strategy: validation

Validate before calling

// check shape against the expected schema
const defs = JSON.parse(unwrapped);
if (!Array.isArray(defs) || !defs.every(d => typeof d.name === 'string' && typeof d.command === 'string')) {
  throw new Error('each MCP server definition needs string name and command');
}

Type guard

function isMcpServerDefinition(d) {
  return typeof d === 'object' && d !== null && typeof d.name === 'string' && typeof d.command === 'string';
}

Try / catch

try {
  let defs = JSON.parse(unwrapped);
  if (!Array.isArray(defs)) throw new Error('expected an array of definitions');
} catch (e) {
  console.error(`Invalid MCP definition list: ${e.message}`);
}

Prevention

When it happens

Trigger: The key holds a JSON string whose inner text is not a JSON array of McpServerDefinition — e.g. an object instead of an array, missing required fields (name/command/args), or wrong field types like a numeric port where a string is expected.

Common situations: Schema drift after a CLI upgrade changed McpServerDefinition fields; hand-written definitions missing a required field; copying an example that no longer matches the current struct.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/20015a790d9d5f1e. Report an issue: GitHub.

Appendix: source

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

        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 73e0f67d83)