{"record":{"id":"c2b6aab977482fe6","repo":"linera-io/linera-protocol","slug":"wrong-json-rpc-version","errorCode":null,"errorMessage":"wrong JSON-RPC version","messagePattern":"wrong JSON-RPC version","errorType":"validation","errorClass":"EthereumQueryError","httpStatus":null,"severity":"error","filePath":"linera-ethereum/src/client.rs","lineNumber":48,"sourceCode":"\n    /// Gets a new ID for the next message.\n    async fn get_id(&self) -> u64;\n\n    /// The function doing the parsing of the input and output.\n    async fn request<T, R>(&self, method: &str, params: T) -> Result<R, Self::Error>\n    where\n        T: Debug + Serialize + Send + Sync,\n        R: DeserializeOwned + Send,\n    {\n        let id = self.get_id().await;\n        let payload = JsonRpcRequest::new(id, method, params);\n        let payload = serde_json::to_vec(&payload)?;\n        let body = self.request_inner(payload).await?;\n        let result = serde_json::from_slice::<JsonRpcResponse>(&body)?;\n        let raw = result.result;\n        let res = serde_json::from_str(raw.get())?;\n        ensure!(id == result.id, EthereumQueryError::IdIsNotMatching);\n        ensure!(\n            \"2.0\" == result.jsonrpc,\n            EthereumQueryError::WrongJsonRpcVersion\n        );\n        Ok(res)\n    }\n}\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct JsonRpcRequest<'a, T> {\n    id: u64,\n    jsonrpc: &'a str,\n    method: &'a str,\n    params: T,\n}\n\nimpl<'a, T> JsonRpcRequest<'a, T> {\n    /// Creates a new JSON RPC request, the id does not matter\n    pub fn new(id: u64, method: &'a str, params: T) -> Self {","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-ethereum/src/client.rs#L30-L66","documentation":"Raised by linera-ethereum's JsonRpcClient::request when the deserialized response's jsonrpc field is not exactly \"2.0\". The client only speaks JSON-RPC 2.0 and verifies the version marker on every reply; a different value means the endpoint is not a conforming Ethereum JSON-RPC 2.0 server (e.g. a 1.0-style server or some other HTTP service that happens to return JSON).","triggerScenarios":"URL pointing at a JSON-RPC 1.0 server or an arbitrary JSON HTTP API that includes a jsonrpc field with another value; mock/test doubles not setting the field correctly; gateways that translate between RPC dialects and drop the version.","commonSituations":"Wrong URL (e.g. an indexer's REST API instead of the node's RPC port); test harnesses with hand-rolled JSON-RPC responders; legacy infrastructure fronting the node.","solutions":["Verify the URL targets the node's JSON-RPC endpoint (default port 8545) and test it: curl -s -X POST -H 'content-type: application/json' --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_blockNumber\",\"params\":[]}' <url>","Fix mock servers and gateways to echo \"jsonrpc\":\"2.0\" in every response","Replace non-conformant front layers or connect directly to the node"],"exampleFix":"// Mock server: return a conforming 2.0 envelope\n// before\n{\"id\": 7, \"result\": \"0x1\"}\n// after\n{\"jsonrpc\": \"2.0\", \"id\": 7, \"result\": \"0x1\"}","handlingStrategy":"validation","validationCode":"async fn speaks_json_rpc_2_0(url: &str) -> bool {\n    let body = r#\"{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"web3_clientVersion\",\"params\":[]}\"#;\n    let resp: serde_json::Value = reqwest::Client::new()\n        .post(url)\n        .header(\"content-type\", \"application/json\")\n        .body(body)\n        .send().await.unwrap()\n        .json().await.unwrap();\n    resp.get(\"jsonrpc\") == Some(&serde_json::json!(\"2.0\"))\n}","typeGuard":"fn is_wrong_json_rpc_version(err: &EthereumQueryError) -> bool {\n    matches!(err, EthereumQueryError::WrongJsonRpcVersion)\n}","tryCatchPattern":"match client.get_balance(address).await {\n    Err(e) if is_wrong_json_rpc_version(&e) => {\n        // Endpoint is not JSON-RPC 2.0; fail fast with a clear config error.\n        Err(anyhow::anyhow!(\"configured Ethereum URL is not a JSON-RPC 2.0 endpoint\"))\n    }\n    other => other,\n}","preventionTips":["Validate the RPC URL with the web3_clientVersion probe at startup, before the bridge starts indexing","Keep mock/test servers conformant: every response must include \"jsonrpc\":\"2.0\" and the request id","Prefer dedicated node RPC ports over generic API gateways for the Ethereum connection"],"tags":["ethereum","json-rpc","version","client","linera-bridge"],"backgroundTag":"json-rpc-protocol-violation","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}