{"record":{"id":"d43bb4e09aea4831","repo":"ultraworkers/claw-code","slug":"mcp-response-for-method-used-mismatched-id-expe","errorCode":null,"errorMessage":"MCP response for {method} used mismatched id: expected {id:?}, got {:?}","messagePattern":"MCP response for (.+?) used mismatched id: expected (.+?), got (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"rust/crates/runtime/src/mcp_stdio.rs","lineNumber":1314,"sourceCode":"        params: Option<TParams>,\n    ) -> io::Result<JsonRpcResponse<TResult>> {\n        let method = method.into();\n        let request = JsonRpcRequest::new(id.clone(), method.clone(), params);\n        self.send_request(&request).await?;\n        let response = self.read_response().await?;\n\n        if response.jsonrpc != \"2.0\" {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"MCP response for {method} used unsupported jsonrpc version `{}`\",\n                    response.jsonrpc\n                ),\n            ));\n        }\n\n        if response.id != id {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"MCP response for {method} used mismatched id: expected {id:?}, got {:?}\",\n                    response.id\n                ),\n            ));\n        }\n\n        Ok(response)\n    }\n\n    pub async fn initialize(\n        &mut self,\n        id: JsonRpcId,\n        params: McpInitializeParams,\n    ) -> io::Result<JsonRpcResponse<McpInitializeResult>> {\n        self.request(id, \"initialize\", Some(params)).await\n    }","sourceCodeStart":1296,"sourceCodeEnd":1332,"githubUrl":"https://github.com/ultraworkers/claw-code/blob/08106b0c3771ef5b4a5aa176acccd460e88b7325/rust/crates/runtime/src/mcp_stdio.rs#L1296-L1332","documentation":"`McpStdioProcess::request` (runtime/src/mcp_stdio.rs:1314) requires the response id to equal the request id. `JsonRpcId` (mcp_stdio.rs:33) is an untagged enum {Number(u64), String, Null} with type-sensitive equality: a server echoing numeric `1` for a request sent as string `\"1\"` mismatches, as does any drifted value. Because request() awaits exactly one response, out-of-order delivery is not the usual cause — wrong echo is.","triggerScenarios":"Server coercing ids to numbers (e.g. JSON.parse then re-emit, or Python int('1')); server echoing a hardcoded id like 0 or 1 for every response; server sending a notification-shaped response with a fresh id; responding to a server-initiated request with the client's id.","commonSituations":"Hand-rolled MCP servers that don't propagate the request id; frameworks that auto-assign sequential ids; string/number confusion across language boundaries (JS BigInt handling, Python str vs int).","solutions":["In the server, copy the request id verbatim — same JSON type and value — into the response.","Prefer numeric u64 ids on the client side if the server stack loses string typing.","If you control both ends, assert id equality in tests for every method."],"exampleFix":"# before (server: hardcoded / coerced id)\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{}}          # request id was \"1\" (string)\n\n# after (server: echo the request id exactly)\n{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"result\":{}}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn ids_compatible(sent: &JsonRpcId, got: &JsonRpcId) -> bool {\n    matches!((sent, got),\n        (JsonRpcId::Number(a), JsonRpcId::Number(b)) if a == b)\n        || matches!((sent, got), (JsonRpcId::String(a), JsonRpcId::String(b)) if a == b)\n        || matches!((sent, got), (JsonRpcId::Null, JsonRpcId::Null))\n}","tryCatchPattern":"match process.request(id.clone(), method, params).await {\n    Err(e) if e.kind() == io::ErrorKind::InvalidData\n        && e.to_string().contains(\"mismatched id\") => {\n        // server coerces/rewrites ids: switch client to numeric u64 ids or fix server echo\n    }\n    other => other,\n}","preventionTips":["Echo the request id verbatim — same JSON type and value (string vs number is a mismatch here)","Prefer numeric u64 ids when the server stack is loose about string typing","Never let a framework auto-assign response ids"],"tags":["mcp","jsonrpc","response-id"],"backgroundTag":"jsonrpc-id-mismatch","analyzedSha":"08106b0c3771ef5b4a5aa176acccd460e88b7325","analyzedAt":"2026-08-18T00:29:38.590Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}