nautechsystems/nautilus_trader · error · anyhow::Error

Independent swap quote returned zero

Error message

Independent swap quote returned zero

What it means

This error is thrown in `verified_swap_amounts` (crates/adapters/blockchain/src/execution/client.rs:4080) after the client obtains an independent Uniswap V3 quote from the on-chain Quoter contract. A zero amount out means the quoter could not produce a valid swap result, so the client refuses to proceed rather than build a trade on a meaningless quote.

Source

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

                .await
        }
        SwapQuoteKind::ExactOutput(amount_out) => {
            verification
                .verify_quote_exact_output_single(
                    &quote_contract,
                    plan.token_in,
                    plan.token_out,
                    amount_out,
                    plan.fee,
                    block,
                )
                .await
        }
    }
}

fn verified_swap_amounts(plan: &SwapPlan, quote: UniswapV3Quote) -> anyhow::Result<(U256, U256)> {
    anyhow::ensure!(
        !quote.amount.is_zero(),
        "Independent swap quote returned zero"
    );
    let base_amount =
        quantity_to_raw_amount(plan.order.quantity(), plan.pool.get_base_token().decimals)?;
    let slippage_bps = plan.slippage_bps;
    match plan.order.order_side() {
        OrderSide::Sell => Ok((
            base_amount,
            derive_min_amount_out(quote.amount, slippage_bps)?,
        )),
        OrderSide::Buy => {
            let ceiling = plan.quote_spend_ceiling.ok_or_else(|| {
                anyhow::anyhow!(
                    "No quote spend ceiling for BUY token pair {} -> {}",
                    plan.token_in,
                    plan.token_out
                )

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check pool liquidity for the token pair/fee tier and use a pool with sufficient reserves for the order size.
  2. Verify plan.token_in, plan.token_out, and plan.fee correspond to an actually deployed pool (see validate_manifest_pool).
  3. Re-run the quote at the current canonical block; ensure the block passed to verify_quote_exact_input_single / verify_quote_exact_output_single is recent.
  4. If the order size legitimately fails, reduce the order quantity so the quote produces a non-zero amount.

Example fix

// before: proceed without checking quote value
let quote = verification.verify_quote_exact_output_single(...).await?;
// after: validate the quote is non-zero and fail fast
let quote = verified_value(
    verification.verify_quote_exact_output_single(...).await,
    "independent swap quote",
)?;
anyhow::ensure!(!quote.amount.is_zero(), "Independent swap quote returned zero");
Defensive patterns

Strategy: validation

Validate before calling

fn quote_is_tradeable(q: &UniswapV3Quote) -> bool { !q.amount.is_zero() }

Type guard

fn is_valid_quote(q: &UniswapV3Quote) -> bool { !q.amount.is_zero() }

Try / catch

let quote = client.verify_swap_quote(...).await?;
if quote.amount.is_zero() {
    return Err(ExecutionError::UnquotablePool { token_in, token_out, fee });
}

Prevention

When it happens

Trigger: Calling verify_swap_quote / verified_swap_amounts when the QuoterV2 contract returns amount==0: an ExactOutput request whose desired output exceeds available pool liquidity, an ExactInput so small it rounds to zero, a wrong/stale block number used for quoting, or a token pair/fee tier with no deployed pool.

Common situations: Quoting a BUY order on a thin/illiquid pool with insufficient reserves; token address or fee-tier misconfiguration so no real pool exists at that key; quoting against an unfunded testnet deployment; a network fork or stale block head returning degenerate quote data.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/a044823371c78232. Report an issue: GitHub.