nautechsystems/nautilus_trader · error
Finalized Swap input {quote_amount} does not match the persi
Error message
Finalized Swap input {quote_amount} does not match the persisted amount {} What it means
For BUY orders, the finalized Swap event's quote-side amount must be positive and equal in absolute value to the persisted plan.amount_in, since for a BUY the quote token is the input. A mismatch means the on-chain quote input differs from the recorded plan amount.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:4785
})?;
let event = dex.parse_swap_event_rpc(log)?;
let (base_amount, quote_amount) =
if plan.pool.get_base_token().address == plan.pool.token0.address {
(event.amount0, event.amount1)
} else {
(event.amount1, event.amount0)
};
let last_qty = match plan.order.order_side() {
OrderSide::Sell => {
anyhow::ensure!(
base_amount.is_positive() && base_amount.unsigned_abs() == plan.amount_in,
"Finalized Swap input {base_amount} does not match the persisted amount {}",
plan.amount_in
);
plan.order.quantity()
}
OrderSide::Buy => {
anyhow::ensure!(
quote_amount.is_positive() && quote_amount.unsigned_abs() == plan.amount_in,
"Finalized Swap input {quote_amount} does not match the persisted amount {}",
plan.amount_in
);
anyhow::ensure!(
base_amount.is_negative(),
"Finalized Swap base amount {base_amount} is not a BUY output"
);
raw_amount_to_quantity(
base_amount.unsigned_abs(),
plan.pool.get_base_token().decimals,
)?
}
};
let block = &included.finality.inclusion_header;
anyhow::ensure!(
block.number == included.block_numberView on GitHub (pinned to 18893faf8b)
Solutions
- Check that the base/quote selection branch matches the pool's token ordering
- Persist amount_in with the same decimals/units the RPC decoder emits
- If the route splits input across multiple pools, sum per-pool inputs rather than comparing plan.amount_in to one leg
- Verify the log corresponds to this plan's swap (tx hash, log index) before comparing amounts
Defensive patterns
Strategy: validation
Validate before calling
if order_side == OrderSide::Buy && !(quote_amount.is_positive() && quote_amount.unsigned_abs() == plan.amount_in) {
return Err(anyhow!("BUY input mismatch: event={} plan={}", quote_amount, plan.amount_in));
} Try / catch
if let Err(e) = verify_finalized_swap(...).await {
if e.to_string().contains("does not match the persisted amount") {
reconcile_with_route_splits(tx_hash).await?;
} else { return Err(e); }
} Prevention
- Persist amount_in in the same units the RPC decoder emits
- Map amount0/amount1 to base/quote once, centrally, from token ordering
- Handle aggregator routes that split input across pools by summing legs
- Confirm the log belongs to this plan's swap before comparing amounts
When it happens
Trigger: Verifying a BUY swap where the selected quote amount is <= 0 or unsigned_abs() != plan.amount_in — caused by wrong base/quote amount mapping (amount0 vs amount1), a plan whose recorded input was changed, or the log belonging to a different swap in the same transaction.
Common situations: Token0/token1 ordering confusion between pool metadata and decoder output; amount_in persisted in different units (wei vs token decimals); executing via an aggregator that split the input across pools so this pool's input is smaller than the plan total.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Finalized Swap input {base_amount} does not match the persis
- Finalized Swap base amount {base_amount} is not a BUY output
- No deployed bytecode at {description} address {address}
- HyperSync parsing of swap event is not defined in this dex:
- Unsupported order type {}; only Market is supported
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/735b8a0274c4be1b.
Report an issue: GitHub.