{"record":{"id":"6ca6c512daeb1c81","repo":"nautechsystems/nautilus_trader","slug":"finalized-swap-side-does-not-match-order","errorCode":null,"errorMessage":"Finalized Swap side {} does not match {} order","messagePattern":"Finalized Swap side (.+?) does not match (.+?) order","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":4824,"sourceCode":"        included.block_number,\n        included.receipt.block_hash\n    );\n    let timestamp_ns = block\n        .timestamp\n        .checked_mul(NANOSECONDS_IN_SECOND)\n        .ok_or_else(|| anyhow::anyhow!(\"Finalized block timestamp overflows nanoseconds\"))?;\n    let mut swap = event.to_pool_swap(\n        plan.pool.chain.clone(),\n        plan.instrument_id,\n        plan.pool.pool_identifier,\n        UnixNanos::from(timestamp_ns),\n    );\n    swap.calculate_trade_info(&plan.pool.token0, &plan.pool.token1, None)?;\n    let trade = swap\n        .trade_info\n        .as_ref()\n        .ok_or_else(|| anyhow::anyhow!(\"Finalized Swap has no calculated trade information\"))?;\n    anyhow::ensure!(\n        trade.order_side == plan.order.order_side(),\n        \"Finalized Swap side {} does not match {} order\",\n        trade.order_side,\n        plan.order.order_side()\n    );\n    let gas_cost = included\n        .receipt\n        .effective_gas_price\n        .checked_mul(U256::from(included.receipt.gas_used))\n        .ok_or_else(|| anyhow::anyhow!(\"Finalized transaction gas commission overflow\"))?;\n    let commission = Money::from_u256(gas_cost, plan.pool.chain.native_currency())?;\n    let trade_digest = keccak256(format!(\"{}:{}\", included.tx_hash, swap.log_index));\n    let trade_digest = trade_digest.to_string();\n    let trade_id = TradeId::new_checked(&trade_digest[2..38])?;\n\n    if plan\n        .order\n        .trade_ids()","sourceCodeStart":4806,"sourceCodeEnd":4842,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L4806-L4842","documentation":"After a finalized swap's trade info is computed, the adapter asserts that the trade's `order_side` matches the side of the originating order in the execution plan. This `ensure!` failure means the on-chain swap executed in the opposite or different direction than the client order requested (e.g. a BUY order produced a SELL-side swap). It guards against executing fills that contradict the user's intent.","triggerScenarios":"A finalized swap's `TradeInfo.order_side` differs from `plan.order.order_side()` — typically when the swap direction through token0/token1 is misinterpreted (quote/base inversion), the order was placed on the wrong side for the pool, or a router routed the swap in the reverse direction.","commonSituations":"Inverted token ordering in pool configuration (token0/token1 swapped relative to the manifest); placing a BUY order against a pool whose price direction the adapter interprets oppositely; copying an order/plan between chains or pools with different token ordering conventions.","solutions":["Check the pool's token0/token1 ordering in the deployment manifest matches what the order side expects","Confirm the order side (Buy/Sell) in the plan is correct for the pool's quote/base direction","Re-derive the swap path so the swap direction aligns with the order side before execution","If using a router, verify it did not flip the swap direction (e.g. exact-input vs exact-output path)"],"exampleFix":"// before: order side assumed to match pool direction\nlet swap = build_swap(plan, included)?;\n// after: assert direction before submitting\nlet expected_side = if swap.token_in == plan.pool.token0 { OrderSide::Buy } else { OrderSide::Sell };\nanyhow::ensure!(expected_side == plan.order.order_side(), \"plan side misconfigured for pool direction\");","handlingStrategy":"validation","validationCode":"// before submitting the plan, confirm side matches pool direction\nlet swap_side = if swap.token_in == plan.pool.token0 { OrderSide::Buy } else { OrderSide::Sell };\nassert_eq!(swap_side, plan.order.order_side(), \"order side inconsistent with pool direction\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = execute_plan(&plan).await {\n    if e.to_string().contains(\"does not match\") {\n        log::error!(\"order/pool side mismatch: review token0/token1 ordering in manifest\");\n    }\n}","preventionTips":["Confirm token0/token1 ordering (by address) when configuring pools in the manifest","Always derive order side from the pool's quote/base orientation, not from intuition","Add a pre-trade assertion comparing plan order side with the intended swap direction"],"tags":["rust","blockchain","order-side","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}