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
- 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
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
- 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
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
- invalid JSON payload at key {MCP_SERVER_DEFINITIONS_KEY}; co
- unavailable credential
- Secret storage write failed for {slot}: {err}. Refusing to w
- {error}; additionally could not verify secret-store rollback
- {error}; additionally failed to restore prior secret-store s
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/20015a790d9d5f1e.
Report an issue: GitHub.