nautechsystems/nautilus_trader · error

{message}

Error message

{message}

What it means

This is the pending-inclusion bail: when awaiting inclusion the outcome is InclusionOutcome::Pending(message), meaning the transaction has not been included within the expected window. The pending reason message is propagated verbatim as the error so the caller knows why inclusion is still pending.

Source

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

                    verify_finalized_transaction(
                        &included,
                        &intent,
                        prepared.nonce,
                        &prepared.raw_tx,
                        self,
                        purpose.as_str(),
                    )
                    .await?,
                );
                self.commit_verified_finality(&included, TransactionStatus::Reverted, &[])
                    .await?;
                self.database
                    .mark_execution_event_emitted(prepared.intent_id, "terminal")
                    .await?;
                self.release_slot();
                anyhow::bail!("Transaction {} reverted on-chain", included.tx_hash)
            }
            InclusionOutcome::Pending(message) => anyhow::bail!(message),
        }
    }

    /// Claims the single in-flight slot before any preparation RPC call, so the `pending`
    /// nonce read stays authoritative: a second transaction is rejected before it can sign.
    fn claim_slot(&self, purpose: TransactionPurpose) -> anyhow::Result<()> {
        let mut slot = self.in_flight.lock();
        if let Some(in_flight) = *slot {
            return Err(in_flight_limit_error(&in_flight));
        }
        *slot = Some(InFlightSlot::Preparing(purpose));
        Ok(())
    }

    /// Runs the read-only pre-signing pipeline: chain ID verification, nonce selection, fee
    /// and gas policy checks, transaction building, and local signing.
    #[expect(
        clippy::too_many_arguments,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the propagated message to see the pending reason, then resubmit with a higher gas price if stuck
  2. Verify the nonce was not consumed or replaced by another transaction
  3. Check transaction hash on a block explorer to confirm mempool status
  4. Increase the inclusion wait timeout or resubmit with speed-up pricing
Defensive patterns

Strategy: retry

Validate before calling

// Confirm nonce is free and gas is competitive before submitting
let pending_nonce = client.pending_nonce(signer).await?;
let gas = client.suggest_gas_price().await?;
anyhow::ensure!(next_nonce == pending_nonce, "nonce mismatch; resync");

Try / catch

match res {
    Err(pending_msg) => {
        // resubmit same nonce with +10-20% gas (speed-up) or cancel
        client.resubmit_with_bump(tx_hash, 1.15).await?;
    }
    Ok(r) => r,
}

Prevention

When it happens

Trigger: After submitting, the inclusion watcher returns Pending — e.g. the transaction is stuck in the mempool, its gas price is too low, or it was replaced/dropped and the watcher timed out.

Common situations: Gas price set too low during network congestion; nonce reuse or replacement by another transaction with the same nonce; RPC node not propagating the transaction; inclusion timeout configured too short.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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