{"record":{"id":"9d1f525b3f34502a","repo":"nautechsystems/nautilus_trader","slug":"simulation-response-does-not-contain-gas-info","errorCode":null,"errorMessage":"Simulation response does not contain gas info","messagePattern":"Simulation response does not contain gas info","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/grpc/client.rs","lineNumber":469,"sourceCode":"    }\n\n    /// Simulate a transaction to estimate gas usage.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if simulation fails.\n    pub async fn simulate_tx(&mut self, tx_bytes: Vec<u8>) -> Result<u64, anyhow::Error> {\n        let req = SimulateRequest {\n            tx_bytes,\n            ..Default::default()\n        };\n        let gas_used = self\n            .tx\n            .simulate(req)\n            .await?\n            .into_inner()\n            .gas_info\n            .ok_or_else(|| anyhow::anyhow!(\"Simulation response does not contain gas info\"))?\n            .gas_used;\n        Ok(gas_used)\n    }\n\n    /// Broadcast a signed transaction.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if broadcasting fails.\n    pub async fn broadcast_tx(&mut self, tx_bytes: Vec<u8>) -> Result<TxHash, anyhow::Error> {\n        let req = BroadcastTxRequest {\n            tx_bytes,\n            mode: BroadcastMode::Sync as i32,\n        };\n        let response = self.tx.broadcast_tx(req).await?.into_inner();\n\n        if let Some(tx_response) = response.tx_response {\n            if tx_response.code != 0 {","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/grpc/client.rs#L451-L487","documentation":"simulate_tx submits a simulated transaction to the tx service and reads gas_used from the optional `gas_info` field; when the node returns a sim response without gas info the library cannot estimate gas and raises this error. This indicates the simulation produced no gas accounting, often because the tx itself failed to execute in simulation.","triggerScenarios":"Calling simulate_tx with a transaction that reverts during simulation (e.g. insufficient balance, invalid order) so the node returns no gas_info, or against a node that doesn't populate gas_info.","commonSituations":"Simulating a market order when the subaccount lacks collateral; node misconfiguration or older node version omitting gas_info; network congestion causing sim aborts.","solutions":["Check the account's on-chain balances/positions; the tx likely fails at execution, removing gas accounting.","Retry the simulation; transient node conditions can drop gas_info.","Use a different RPC node or increase the sim timeout.","Fall back to a conservative hardcoded gas limit instead of the simulated value."],"exampleFix":"// before\nlet gas = client.simulate_tx(&tx_bytes).await?;\n// after: fallback gas limit on missing gas info\nlet gas = match client.simulate_tx(&tx_bytes).await {\n    Ok(g) => g,\n    Err(_) if fallback_allowed => DEFAULT_SIM_GAS_LIMIT,\n    Err(e) => return Err(e),\n};","handlingStrategy":"fallback","validationCode":"// ensure subaccount has sufficient collateral before simulating\nlet sub = client.get_subaccount(owner, 0).await?;\nanyhow::ensure!(has_enough_equity(&sub, order), \"insufficient equity for order\");","typeGuard":null,"tryCatchPattern":"let gas_used = match client.simulate_tx(&tx_bytes).await {\n    Ok(g) if g > 0 => g,\n    Ok(_) | Err(_) => DEFAULT_SIM_GAS_LIMIT, // conservative fallback\n};","preventionTips":["Pre-check balances/positions before simulation","Use reputable RPC nodes that populate gas_info","Always carry a conservative fallback gas limit"],"tags":["grpc","cosmos","simulation","gas"],"backgroundTag":"unexpected-response-shape","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"}