nautechsystems/nautilus_trader · error
Finalized Swap side {} does not match {} order
Error message
Finalized Swap side {} does not match {} order What it means
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.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:4824
included.block_number,
included.receipt.block_hash
);
let timestamp_ns = block
.timestamp
.checked_mul(NANOSECONDS_IN_SECOND)
.ok_or_else(|| anyhow::anyhow!("Finalized block timestamp overflows nanoseconds"))?;
let mut swap = event.to_pool_swap(
plan.pool.chain.clone(),
plan.instrument_id,
plan.pool.pool_identifier,
UnixNanos::from(timestamp_ns),
);
swap.calculate_trade_info(&plan.pool.token0, &plan.pool.token1, None)?;
let trade = swap
.trade_info
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Finalized Swap has no calculated trade information"))?;
anyhow::ensure!(
trade.order_side == plan.order.order_side(),
"Finalized Swap side {} does not match {} order",
trade.order_side,
plan.order.order_side()
);
let gas_cost = included
.receipt
.effective_gas_price
.checked_mul(U256::from(included.receipt.gas_used))
.ok_or_else(|| anyhow::anyhow!("Finalized transaction gas commission overflow"))?;
let commission = Money::from_u256(gas_cost, plan.pool.chain.native_currency())?;
let trade_digest = keccak256(format!("{}:{}", included.tx_hash, swap.log_index));
let trade_digest = trade_digest.to_string();
let trade_id = TradeId::new_checked(&trade_digest[2..38])?;
if plan
.order
.trade_ids()View on GitHub (pinned to 18893faf8b)
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)
Example fix
// before: order side assumed to match pool direction
let swap = build_swap(plan, included)?;
// after: assert direction before submitting
let expected_side = if swap.token_in == plan.pool.token0 { OrderSide::Buy } else { OrderSide::Sell };
anyhow::ensure!(expected_side == plan.order.order_side(), "plan side misconfigured for pool direction"); Defensive patterns
Strategy: validation
Validate before calling
// before submitting the plan, confirm side matches pool direction
let swap_side = if swap.token_in == plan.pool.token0 { OrderSide::Buy } else { OrderSide::Sell };
assert_eq!(swap_side, plan.order.order_side(), "order side inconsistent with pool direction"); Try / catch
if let Err(e) = execute_plan(&plan).await {
if e.to_string().contains("does not match") {
log::error!("order/pool side mismatch: review token0/token1 ordering in manifest");
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid venue {}, expected Blockchain DEX format
- {evidence} side {actual} does not match known order side {ex
- Unsupported `OrderSide` for Binance: {value:?}
- invalid OrderSide: must be Buy or Sell, was {side}
- Failed to load active execution intent: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6ca6c512daeb1c81.
Report an issue: GitHub.