{"record":{"id":"2d559079c50e9b01","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-debug-tracetransaction-response","errorCode":null,"errorMessage":"Failed to parse debug_traceTransaction response","messagePattern":"Failed to parse debug_traceTransaction response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/http.rs","lineNumber":831,"sourceCode":"                        \"withLog\": false,\n                    },\n                }\n            ],\n        });\n        let bytes = self\n            .send_rpc_request(request, Some(EXECUTION_RPC_TIMEOUT_SECS))\n            .await\n            .map_err(|e| match e {\n                BlockchainRpcClientError::ClientError(message)\n                    if message.contains(\"redirect response rejected\") =>\n                {\n                    anyhow::anyhow!(\"debug_traceTransaction redirect rejected\")\n                }\n                _ => anyhow::anyhow!(\"debug_traceTransaction request failed\"),\n            })?;\n        let parsed =\n            serde_json::from_slice::<RpcNodeHttpResponse<serde_json::Value>>(bytes.as_ref())\n                .map_err(|_| anyhow::anyhow!(\"Failed to parse debug_traceTransaction response\"))?;\n        if parsed.jsonrpc.is_none()\n            && let (Some(code), Some(_)) = (parsed.code, parsed.message)\n        {\n            return trace_probe_result(code);\n        }\n\n        if let Some(error) = parsed.error {\n            return trace_probe_result(error.code);\n        }\n        anyhow::ensure!(\n            parsed.result.is_some(),\n            \"debug_traceTransaction returned no result\"\n        );\n        Ok(())\n    }\n\n    /// Broadcasts a signed raw transaction via `eth_sendRawTransaction`.\n    ///","sourceCodeStart":813,"sourceCodeEnd":849,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/http.rs#L813-L849","documentation":"This error is thrown when the raw HTTP body returned for a `debug_traceTransaction` JSON-RPC call cannot be deserialized into the expected `RpcNodeHttpResponse<serde_json::Value>` envelope. It means the node (or an intermediary proxy) returned a response body that is not well-formed JSON or not shaped like a JSON-RPC response. The library throws it inside `probe_call_trace` after the request itself succeeded at the transport level.","triggerScenarios":"Calling `probe_call_trace` against an execution endpoint whose `debug_traceTransaction` reply is not a valid JSON-RPC response object (missing/invalid JSON structure), e.g. an HTML error page, truncated body, or a proxy/CORS interstitial, so `serde_json::from_slice::<RpcNodeHttpResponse<Value>>` fails.","commonSituations":"Node behind a reverse proxy (nginx/Cloudflare) that intercepts the request and returns HTML; tracing module (`debug_*` namespace) handled by a different upstream than expected; load balancer returning 502/504 HTML bodies; extremely large traces causing gateway body truncation or timeouts.","solutions":["Curl the endpoint's debug_traceTransaction directly and inspect the raw body for HTML/proxy error pages.","Point the execution endpoint at a node with the debug API enabled (e.g. geth --http.api debug,erigon) rather than a proxy that strips or fails it.","Reduce trace scope (fewer blocks / simpler call) if body size limits at the proxy are truncating the response.","Retry, or switch to a fallback RPC provider if the node is intermittently returning malformed bodies."],"exampleFix":"// before\nlet url = \"http://proxy.example.com/v1\"; // proxy returns HTML on trace APIs\n// after\nlet url = \"https://geth-node.internal:8545\"; // direct node with debug API enabled","handlingStrategy":"try-catch","validationCode":"// Pre-check: ensure endpoint returns JSON, not HTML\nlet head = reqwest::Client::new().post(endpoint)\n    .json(&serde_json::json!({\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_chainId\",\"params\":[]}))\n    .send().await?;\nlet ct = head.headers().get(reqwest::header::CONTENT_TYPE).and_then(|v| v.to_str().ok()).unwrap_or(\"\");\nif !ct.contains(\"json\") { return Err(anyhow!(\"endpoint does not return JSON: content-type={ct}\")); }","typeGuard":"fn looks_like_json_rpc_response(body: &[u8]) -> bool {\n    serde_json::from_slice::<serde_json::Value>(body)\n        .map(|v| v.get(\"jsonrpc\").is_some() || v.get(\"result\").is_some() || v.get(\"error\").is_some())\n        .unwrap_or(false)\n}","tryCatchPattern":"match probe_call_trace(tx_hash) {\n    Err(e) if e.to_string().contains(\"Failed to parse debug_traceTransaction response\") => {\n        tracing::warn!(%tx_hash, \"malformed trace response; falling back to alternate node\");\n        fallback_node.probe_call_trace(tx_hash)\n    }\n    other => other,\n}","preventionTips":["Curl debug_traceTransaction once when adding a new endpoint to confirm a JSON body and content-type.","Avoid routing trace requests through proxies/LBs that can inject HTML error pages.","Monitor for 502/504 HTML bodies from gateways and alert on content-type drift."],"tags":["json","rpc","tracing","network"],"backgroundTag":"invalid-json-response","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}