{"record":{"id":"9c4be654d45b917f","repo":"nautechsystems/nautilus_trader","slug":"e-9c4be6","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/grpc/client.rs","lineNumber":516,"sourceCode":"            ))\n        }\n    }\n\n    /// Query transaction by hash.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the query fails.\n    pub async fn get_tx(&mut self, hash: &str) -> Result<Tx, anyhow::Error> {\n        let req = GetTxRequest {\n            hash: hash.to_string(),\n        };\n        let response = self.tx.get_tx(req).await?.into_inner();\n\n        if let Some(tx) = response.tx {\n            // Convert through bytes since the types are incompatible\n            let tx_bytes = tx.encode_to_vec();\n            Tx::try_from(tx_bytes.as_slice()).map_err(|e| anyhow::anyhow!(\"{e}\"))\n        } else {\n            anyhow::bail!(\"Transaction not found\")\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use rstest::rstest;\n\n    use super::*;\n\n    #[rstest]\n    fn test_height_ordering() {\n        let h1 = Height(100);\n        let h2 = Height(200);\n        assert!(h1 < h2);\n        assert_eq!(h1, Height(100));","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/grpc/client.rs#L498-L534","documentation":"get_tx queries the tx service by hash and converts the returned raw tx bytes back into a typed Tx via Tx::try_from; the bare `{e}` wraps any conversion failure. The lookup itself succeeded but the on-chain tx bytes could not be decoded into the local Tx type, usually due to proto schema mismatch.","triggerScenarios":"Calling get_tx for a hash whose stored tx contains message types or field versions the local Tx type cannot decode (e.g. txs created by a newer client or with extension options).","commonSituations":"Fetching a tx created by a different client version with mismatched proto definitions; txs containing extension/non-standard options; ibc-proto/cosmos-sdk version skew between writer and reader.","solutions":["Read the inner error to identify which field/type failed conversion and update proto crates accordingly.","Align ibc-proto/cosmos-sdk-proto versions with those used to broadcast the tx.","If only the hash/result is needed, use the raw response fields instead of full Tx conversion.","Skip unsupported extension_option fields or strip them before decoding when feasible."],"exampleFix":"// before\nTx::try_from(tx_bytes.as_slice()).map_err(|e| anyhow::anyhow!(\"{e}\"))\n// after: add context for diagnosability\nTx::try_from(tx_bytes.as_slice())\n    .map_err(|e| anyhow::anyhow!(\"Failed to decode tx {} from chain response: {e}\", hex::encode(hash)))","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.get_tx(&hash).await {\n    Ok(tx) => Ok(tx),\n    Err(e) if e.to_string().contains(\"decode\") || e.to_string().contains(\"Unknown\") => {\n        // schema mismatch: log and degrade to raw response handling\n        tracing::warn!(\"tx decode failed for {hash}: {e:#}\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Keep proto crate versions in sync with the broadcasting client","When only tx results are needed, avoid full Tx re-decoding","Test tx round-trips (broadcast then get_tx) in CI against the target network"],"tags":["grpc","cosmos","transaction","decoding"],"backgroundTag":"protobuf-unmarshal-failed","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"}