nautechsystems/nautilus_trader · error

A {} transaction is being prepared; at most one transaction

Error message

A {} transaction is being prepared; at most one transaction can be in flight

What it means

The execution client enforces a strict single-transaction-in-flight model. This error is raised when a new transaction is attempted while the in-flight slot is occupied by a transaction still in the 'Preparing' phase; the message names the purpose currently preparing.

Source

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

    finalized_headers: Vec<ExecutionVerifiedHeader>,
}

#[derive(Debug, Clone, Copy)]
enum TransactionAuthorization {
    Wrap {
        weth: Address,
    },
    Approve {
        token: Address,
        router: Address,
        amount: U256,
    },
}

/// The single-in-flight limit error naming the transaction currently occupying the slot.
fn in_flight_limit_error(slot: &InFlightSlot) -> anyhow::Error {
    match slot {
        InFlightSlot::Preparing(purpose) => anyhow::anyhow!(
            "A {} transaction is being prepared; at most one transaction can be in flight",
            purpose.as_str()
        ),
        InFlightSlot::Recovering(recovery) => anyhow::anyhow!(
            "Execution intent {} ({}, nonce {}) retains signer ownership pending recovery; at most one transaction can be in flight",
            recovery.intent_id,
            recovery.purpose.as_str(),
            recovery.nonce
        ),
        InFlightSlot::AwaitingFinality(in_flight) => anyhow::anyhow!(
            "Transaction {} (intent {}, {}, nonce {}) is still awaiting finality; at most one transaction can be in flight",
            in_flight.tx_hash,
            in_flight.intent_id,
            in_flight.purpose.as_str(),
            in_flight.nonce
        ),
    }
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Wait for the in-flight transaction to finish (poll its state or await completion) before submitting the next one.
  2. Serialize submissions: queue orders and process one at a time, or use one client per strategy thread.
  3. Recover the stuck preparation — if it never completes, use the recovery path to release the slot.
  4. Check RPC latency; slow eth_* calls extend the preparing window and increase collisions.

Example fix

// before: overlapping submissions
client.submit_order(order_a)?;
client.submit_order(order_b)?; // slot still held by a
// after: await completion first
client.submit_order(order_a)?;
client.await_in_flight_complete().await?;
client.submit_order(order_b)?;
Defensive patterns

Strategy: retry

Validate before calling

if client.in_flight_slot_occupied() { queue_order(order); return; }

Try / catch

match client.submit_order(order) { Err(e) if e.to_string().contains("at most one transaction can be in flight") => { wait_for_slot().await; retry(order); } Ok(r) => r }

Prevention

When it happens

Trigger: Calling submit_order (or any operation needing the slot) while a previous swap/wrap/approve transaction is still being prepared and has not completed or released the slot.

Common situations: Submitting orders too fast from a strategy loop; a prior preparation blocked on a slow RPC call holding the slot; concurrent threads sharing one client without synchronization.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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