nautechsystems/nautilus_trader · error

Transaction {} (intent {}, {}, nonce {}) is still awaiting f

Error message

Transaction {} (intent {}, {}, nonce {}) is still awaiting finality; at most one transaction can be in flight

What it means

Raised when the in-flight slot holds a transaction that has been broadcast but is still awaiting finality (confirmation on chain). The client blocks any new transaction until the pending one reaches finality; the message identifies the tx hash, intent, purpose, and nonce.

Source

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

        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
        ),
    }
}

/// Releases a pre-signature slot claim when the slot is still in the preparing state.
///
/// Aborted or failed preparation can leave a claim behind; because no signed transaction
/// exists for a preparing slot, releasing it cannot strand a broadcastable signature.
fn release_preparing_slot(in_flight: &Mutex<Option<InFlightSlot>>) {
    let mut slot = in_flight.lock();
    if matches!(*slot, Some(InFlightSlot::Preparing(_))) {
        *slot = None;
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Wait for the pending transaction to finalize; poll its receipt or await the finality future before submitting again.
  2. Speed up the stuck tx via a replacement with higher gas (same nonce) if miners are slow.
  3. Increase submission interval or implement an outbound order queue in the strategy.
  4. Verify RPC connectivity — a lagging node may delay finality detection.

Example fix

// before: submit during pending finality
client.submit_order(order_b)?; // tx 0xdef... still awaiting finality
// after: wait for finality
client.await_transaction_finality("0xdef...").await?;
client.submit_order(order_b)?;
Defensive patterns

Strategy: retry

Validate before calling

if let Some(tx) = client.pending_in_flight() { client.await_transaction_finality(tx.tx_hash).await?; }

Type guard

fn is_awaiting_finality(slot: &InFlightSlot) -> bool { matches!(slot, InFlightSlot::AwaitingFinality(_)) }

Try / catch

match client.submit_order(order) { Err(e) if e.to_string().contains("awaiting finality") => { wait_with_backoff().await; retry(order); } Ok(r) => r }

Prevention

When it happens

Trigger: Submitting a new transaction while a previously sent transaction (given by tx_hash) has not yet reached the configured finality depth/confirmations.

Common situations: Slow block times or low gas price making confirmation take longer than the strategy's submission cadence; high-frequency strategy loop outpacing chain finality; RPC lag reporting stale receipt status.

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/5f15acdfa357c518. Report an issue: GitHub.