nautechsystems/nautilus_trader · error · anyhow::Error

Swap quote failed for {instrument_id}: {e}

Error message

Swap quote failed for {instrument_id}: {e}

What it means

The local pool profiler's swap_exact_in(amount_in, zero_for_one, None) simulation returned an error while trying to quote the exact-input swap. The underlying cause is appended ({e}) and typically comes from the tick-walk math: not enough (or no) liquidity in the direction being traded to consume amount_in within the simulated range, or other arithmetic infeasibility in the local pool state.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:1255

                    "No pool profiler for {instrument_id}; an active data subscription is required to quote the swap"
                )
            })?;

        if !profiler.is_initialized {
            anyhow::bail!("Pool profiler for {instrument_id} is not initialized");
        }
        let profiler_block = profiler
            .last_processed_event
            .as_ref()
            .map(|position| position.number)
            .ok_or_else(|| {
                anyhow::anyhow!("Pool profiler for {instrument_id} has processed no events")
            })?;

        let zero_for_one = base_token.address == pool.token0.address;
        let quote = profiler
            .swap_exact_in(amount_in, zero_for_one, None)
            .map_err(|e| anyhow::anyhow!("Swap quote failed for {instrument_id}: {e}"))?;

        let amount_filled = if zero_for_one {
            quote.amount0
        } else {
            quote.amount1
        };

        if amount_filled != I256::from(amount_in) {
            anyhow::bail!(
                "Local quote for {instrument_id} filled {amount_filled} of the {amount_in} order amount; pool liquidity cannot fill the order"
            );
        }

        let quoted_amount_out = exact_output_amount(&quote, zero_for_one)?;
        let min_amount_out = derive_min_amount_out(quoted_amount_out, slippage_bps)?;

        self.ensure_transaction_ready(TransactionPurpose::Swap)?;

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Reduce the order size and retry; the separate 'filled' check shows how much the pool could actually absorb
  2. Check the pool's current liquidity and tick range on-chain (or via the data feed) to size orders within available depth
  3. Confirm the profiler is current (recent events processed) before concluding liquidity is genuinely insufficient
  4. Route around dead pools: de-list instruments whose profiler repeatedly fails to quote

Example fix

# before: order sized far above pool depth
qty = Quantity.from_raw(instrument_id, 10**24)
self.submit_order(market_order(instrument_id, qty))  # Swap quote failed

# after: size within a fraction of observed fill capacity
last_fill_raw = self._observed_max_fill_raw  # tracked from quotes/deltas
qty = Quantity.from_raw(instrument_id, min(10**24, last_fill_raw // 4))
self.submit_order(market_order(instrument_id, qty))
Defensive patterns

Strategy: validation

Validate before calling

# Size orders within observed pool depth before submitting
last_quote = self.cache.quote_tick(instrument_id)
assert last_quote is not None, 'no quote yet'
max_raw = int(self._max_observed_fill_raw * 0.25)  # quarter of observed absorption
assert int(order_qty_raw) <= max_raw, f'{instrument_id}: size exceeds local depth estimate'

Try / catch

try:
    self.submit_order(order)
except Exception as e:
    if 'Swap quote failed' in str(e):
        self._max_observed_fill_raw //= 2  # back off size and retry next signal
        return
    raise

Prevention

When it happens

Trigger: submit_order whose amount_in exceeds what the profiler's reconstructed liquidity can absorb in zero_for_one (or the reverse) direction; quoting against a stale/partial pool state after large liquidity removals; amount_in so large the tick walk runs out of initialized ticks.

Common situations: Thin single-sided liquidity pools; trading right after an LP burned most liquidity; order sizing derived from a different venue's depth; profiler state lagging recent Swap/Burn events.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/4858adcc28c534f3. Report an issue: GitHub.