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
- Read the propagated message to see the pending reason, then resubmit with a higher gas price if stuck
- Verify the nonce was not consumed or replaced by another transaction
- Check transaction hash on a block explorer to confirm mempool status
- 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
- Track nonce usage centrally to avoid collisions/replacements
- Price gas from live network data, not static config
- Set inclusion timeouts generously under congested conditions
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
- Failed to record prepared execution intent: {e}
- Failed to start replacement transaction persistence: {e}
- Failed to retire replaced execution hash: {e}
- Failed to mark execution intent replaced: {e}
- Failed to record replacement transition: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e9b36c9628a0f1a4.
Report an issue: GitHub.