{"record":{"id":"20015a790d9d5f1e","repo":"Hmbown/CodeWhale","slug":"invalid-mcp-server-definition-list-in-key-mcp-ser","errorCode":null,"errorMessage":"invalid MCP server definition list in key {MCP_SERVER_DEFINITIONS_KEY}; contents were omitted","messagePattern":"invalid MCP server definition list in key (.+?); contents were omitted","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/cli/src/lib.rs","lineNumber":4367,"sourceCode":"        Err(err) => {\n            eprintln!(\n                \"warning: failed to parse persisted MCP server definitions ({MCP_SERVER_DEFINITIONS_KEY}): {err}\"\n            );\n            Vec::new()\n        }\n    }\n}\n\nfn parse_mcp_server_definitions(raw: &str) -> Result<Vec<McpServerDefinition>> {\n    if let Ok(parsed) = serde_json::from_str::<Vec<McpServerDefinition>>(raw) {\n        return Ok(parsed);\n    }\n\n    let unwrapped: String = serde_json::from_str(raw).map_err(|_| {\n        anyhow!(\"invalid JSON payload at key {MCP_SERVER_DEFINITIONS_KEY}; contents were omitted\")\n    })?;\n    serde_json::from_str::<Vec<McpServerDefinition>>(&unwrapped).map_err(|_| {\n        anyhow!(\n            \"invalid MCP server definition list in key {MCP_SERVER_DEFINITIONS_KEY}; contents were omitted\"\n        )\n    })\n}\n\nfn persist_mcp_server_definitions(\n    store: &mut ConfigStore,\n    definitions: &[McpServerDefinition],\n) -> Result<()> {\n    let encoded =\n        serde_json::to_string(definitions).context(\"failed to encode MCP server definitions\")?;\n    store\n        .config\n        .set_value(MCP_SERVER_DEFINITIONS_KEY, &encoded)?;\n    store.save()\n}\n\n/// Delegate a long-running server command (`serve --http`/`--mobile`,","sourceCodeStart":4349,"sourceCodeEnd":4385,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/cli/src/lib.rs#L4349-L4385","documentation":"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.","triggerScenarios":"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).","commonSituations":"Old-version persisted payloads read by a newer CLI after a schema change; hand-crafted definitions guessing at field names.","solutions":["Delete the key and re-register the servers with the current CLI version so it persists the current schema","Or fix the inner JSON to match the current definition schema (verify field names against the version in use)","Prefer managing definitions through the CLI's mcp commands rather than by hand"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn is_valid_definition_list(raw: &str) -> bool {\n    let inner: serde_json::Value = match serde_json::from_str(raw) {\n        Ok(v) => v,\n        Err(_) => return false,\n    };\n    inner.as_array().is_some_and(|items| {\n        items.iter().all(|item| item.is_object() && item.get(\"command\").is_some_and(serde_json::Value::is_string))\n    })\n}","tryCatchPattern":null,"preventionTips":["After upgrading the CLI, re-register MCP servers once so payloads re-persist in the current schema","Do not hand-guess McpServerDefinition field names; consult the version's schema","Treat the stderr warning as a signal that the persisted list was dropped, not silently merged"],"tags":["cli","mcp","config","json","schema-mismatch","rust"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}