nautechsystems/nautilus_trader · error

Router allowance {allowance} is below the swap amount {} for

Error message

Router allowance {allowance} is below the swap amount {} for input token {}; approve the router explicitly before submitting

What it means

Pre-trade check that reads the ERC-20 allowance of the configured wallet for the swap router on the input token, and rejects when allowance < plan.amount_in. The blockchain execution client deliberately never auto-approves, because an on-chain approval is a state-changing transaction that costs gas and widens token access; the caller must approve the router explicitly.

Source

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

    ] {
        let code = executor.http_rpc_client.get_code(&address).await?;
        if code.is_empty() {
            anyhow::bail!("No deployed bytecode at {description} address {address}");
        }
    }

    let erc20_contract = Erc20Contract::new_with_timeout(
        executor.http_rpc_client.clone(),
        Some(EXECUTION_RPC_TIMEOUT_SECS),
        true,
    );

    let allowance = erc20_contract
        .allowance(&plan.token_in, &executor.wallet_address, &plan.router)
        .await?;

    if allowance < plan.amount_in {
        anyhow::bail!(
            "Router allowance {allowance} is below the swap amount {} for input token {}; approve the router explicitly before submitting",
            plan.amount_in,
            plan.token_in
        );
    }

    let balance = erc20_contract
        .balance_of(&plan.token_in, &executor.wallet_address)
        .await?;

    if balance < plan.amount_in {
        anyhow::bail!(
            "Input token {} balance {balance} is below the swap amount {}",
            plan.token_in,
            plan.amount_in
        );
    }

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Send an ERC-20 approve(plan.router, amount >= plan.amount_in) transaction from the configured wallet for plan.token_in, then retry the swap
  2. Grant a larger or max allowance if frequent swaps are expected, accepting the standard approval-risk tradeoff
  3. Verify the approval is on the same chain and for the exact router address in the SwapPlan
  4. Reduce plan.amount_in to fit within the existing allowance

Example fix

// before: no approval, swap fails precheck with
// 'Router allowance 0 is below the swap amount ...'

// after: approve the router once from the wallet
let erc20 = Erc20Contract::new(http_rpc_client.clone());
let _receipt = erc20
    .approve(&token_in, &router, U256::MAX)
    .await?; // or the exact swap amount
Defensive patterns

Strategy: validation

Validate before calling

// Before submitting, confirm allowance >= amount_in and approve if needed
let allowance = erc20.allowance(&token_in, &wallet, &router).await?;
if allowance < amount_in {
    erc20.approve(&token_in, &router, amount_in).await?; // explicit approval tx
}

Type guard

fn has_sufficient_allowance(allowance: U256, amount_in: U256) -> bool { allowance >= amount_in }

Try / catch

match execute_swap(plan).await {
    Err(e) if e.to_string().contains("Router allowance") => {
        // deterministic precondition: approve, then retry once with a fresh plan
        approve_router(&plan.token_in, &plan.router, plan.amount_in).await?;
        execute_swap(plan).await
    }
    other => other,
}

Prevention

When it happens

Trigger: Submitting a swap when allowance(owner=wallet_address, spender=plan.router) on plan.token_in is zero or below plan.amount_in: first-ever swap with a token, a previously granted exact-size allowance consumed by earlier swaps, an allowance granted to a different router address than plan.router, or an increased order size beyond the approved amount.

Common situations: Fresh wallet or fresh deployment with no approvals yet; switching the plan to a new router (aggregator/uniswap version) while approvals still point at the old one; allowance used down by repeated swaps; approval performed on the wrong chain or for the wrong token.

Related errors


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