{"record":{"id":"d5432189497953e4","repo":"Hmbown/CodeWhale","slug":"mcp-server-server-method-received-a-child-message-without","errorCode":null,"errorMessage":"MCP server '{server}': {method} received a child message without jsonrpc \"2.0\"","messagePattern":"MCP server '(.+?)': (.+?) received a child message without jsonrpc \"2\\.0\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mcp/src/stdio_client.rs","lineNumber":916,"sourceCode":"                    bail!(\"MCP server '{server}': {method} timed out after {timeout:?}\");\n                }\n                Err(RecvTimeoutError::Disconnected) => {\n                    bail!(\n                        \"MCP server '{server}': process closed stdout before answering {method}{}\",\n                        self.exit_note()\n                    );\n                }\n            };\n\n            // Servers occasionally emit banners or log lines on stdout. They\n            // are skipped; only the matching response ends the wait. Valid\n            // requests and notifications are handled by the reader before\n            // they reach this rendezvous.\n            let Ok(message) = serde_json::from_str::<Value>(&line) else {\n                continue;\n            };\n            if message.get(\"jsonrpc\").and_then(Value::as_str) != Some(\"2.0\") {\n                bail!(\n                    \"MCP server '{server}': {method} received a child message without jsonrpc \\\"2.0\\\"\"\n                );\n            }\n            if message.get(\"id\").and_then(Value::as_u64) != Some(id) {\n                continue;\n            }\n            if let Some(error) = message.get(\"error\") {\n                bail!(\"MCP server '{server}': {method} failed: {error}\");\n            }\n            return message.get(\"result\").cloned().with_context(|| {\n                format!(\n                    \"MCP server '{server}': {method} response contained neither result nor error\"\n                )\n            });\n        }\n    }\n\n    /// The child's exit status, when it has one, for appending to a failure","sourceCodeStart":898,"sourceCodeEnd":934,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/mcp/src/stdio_client.rs#L898-L934","documentation":"After parsing a stdout line as JSON, request() requires every message to carry `\"jsonrpc\": \"2.0\"`. A message reaching the rendezvous without the correct jsonrpc version fails fast with this error, since it indicates a non-conformant peer rather than a matching response.","triggerScenarios":"The child sends a well-formed JSON line over stdout that lacks the jsonrpc field or has a value other than \"2.0\" (and is not filtered earlier by the reader as a notification/request).","commonSituations":"Servers implementing a different JSON-RPC dialect or version; hand-rolled servers omitting the jsonrpc field in responses; middleware rewriting messages.","solutions":["Fix the server to include `\"jsonrpc\":\"2.0\"` on every response message, per the MCP/JSON-RPC 2.0 spec.","Inspect the child's stdout to see the offending message.","Update or replace non-conformant server implementations.","If a proxy rewrites messages, ensure it preserves the jsonrpc field."],"exampleFix":"// before\n{\"id\":1,\"result\":{...}}\n// after\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{...}}","handlingStrategy":"validation","validationCode":"fn is_jsonrpc_20(msg: &serde_json::Value) -> bool {\n    msg.get(\"jsonrpc\").and_then(serde_json::Value::as_str) == Some(\"2.0\")\n}\n// validate a captured line before feeding it through the client in tests","typeGuard":null,"tryCatchPattern":"match client.request(method, params, timeout) {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"without jsonrpc\") => {\n        eprintln!(\"server sent a non-2.0 JSON-RPC message; check server implementation\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Validate server responses against the JSON-RPC 2.0 schema in the server's test suite.","Ensure every emitted message includes \"jsonrpc\":\"2.0\".","If a proxy rewrites messages, preserve the jsonrpc field.","Snapshot-test raw stdout lines of new server integrations."],"tags":["mcp","json-rpc","protocol"],"backgroundTag":"unexpected-response-shape","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}