nautechsystems/nautilus_trader · error · anyhow::Error
Included wrap transaction {tx_hash} has invalid block number
Error message
Included wrap transaction {tx_hash} has invalid block number 0 What it means
ensure_wrap_balance_increase (crates/adapters/blockchain/src/execution/client.rs:680) verifies a wrapped-native deposit by reading the WETH balance at block-1 and at the inclusion block; block_number.checked_sub(1) fails only when the receipt reported the wrap transaction as included in block 0. On production chains block 0 is genesis and contains no ordinary transactions, so a zero block number indicates a malformed or fabricated receipt from the RPC node, not a real inclusion. The check runs both in the live wrap path and in restart reconciliation.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:680
let code = self.http_rpc_client.get_code(address).await?;
if code.is_empty() {
anyhow::bail!("No deployed bytecode at configured {description} address {address}");
}
Ok(())
}
/// Ensures the wrapped native token balance increased by exactly `amount_wei` across the
/// block that included transaction `tx_hash`, reading both balances at their historical
/// blocks. Shared by the live wrap path and restart reconciliation.
async fn ensure_wrap_balance_increase(
&self,
weth_address: &Address,
amount_wei: U256,
tx_hash: B256,
block_number: u64,
) -> anyhow::Result<()> {
let previous_block = block_number.checked_sub(1).ok_or_else(|| {
anyhow::anyhow!("Included wrap transaction {tx_hash} has invalid block number 0")
})?;
let balance_before = self
.erc20_contract
.balance_of_at(weth_address, &self.wallet_address, previous_block)
.await
.with_context(|| {
format!(
"failed to read WETH balance before included transaction {tx_hash} at block {previous_block}"
)
})?;
let balance_after = self
.erc20_contract
.balance_of_at(weth_address, &self.wallet_address, block_number)
.await
.with_context(|| {
format!(
"failed to read WETH balance after included transaction {tx_hash} at block {block_number}"
)View on GitHub (pinned to d1527c24af)
Solutions
- Point the client at a healthy, fully synced RPC endpoint (established provider or own synced node) and retry the wrap.
- Look the transaction hash up in a block explorer and confirm which block actually included it.
- If it recurs on a private chain, upgrade or reconfigure the node software so receipts carry correct block numbers.
- If stuck at connect-time reconciliation, resolve the persisted intent in Postgres (verify on-chain state first) so the poisoned receipt does not block every restart.
Defensive patterns
Strategy: try-catch
Type guard
fn is_invalid_block_number(e: &anyhow::Error) -> bool {
e.to_string().contains("invalid block number 0")
} Try / catch
if let Err(e) = client.wrap(amount_wei).await {
if is_invalid_block_number(&e) {
// RPC served a malformed receipt; do not retry against the same node blindly
log::error!("RPC returned an inclusion block of 0; switching endpoint required: {e}");
return Err(e);
}
return Err(e);
} Prevention
- Use a reputable, fully synced RPC provider for execution paths.
- Monitor node health and syncing status; avoid nodes mid-sync for transaction workflows.
- On private chains, verify receipt block numbering before enabling wrap operations.
- Keep a fallback RPC endpoint configured so a bad node can be swapped quickly.
When it happens
Trigger: The RPC node returns a receipt with block_number 0 for the wrap transaction (misbehaving, forked, or pruned node; mock/dev RPC returning placeholder receipts); reconciling a persisted wrap intent whose recorded inclusion block is 0; a local test chain that numbers the first block 0 and reports receipts accordingly.
Common situations: Using a cheap or overloaded public RPC endpoint that serves garbage historical data; running against an in-process anvil/hardhat-style node with non-standard genesis handling; a node still syncing serving incomplete receipts.
Related errors
- WETH balance overflow for included transaction {tx_hash} at
- Replacement hash {transaction_hash} conflicts with another i
- Finalized block {} does not contain transaction {}
- Unsupported blockchain {blockchain} for RPC connection
- RPC parsing of pool created event is not defined in this dex
AI-assisted analysis of nautechsystems/nautilus_trader@d1527c24af (2026-08-21).
Data as JSON: /api/errors/7bd403f83e1986d6.
Report an issue: GitHub.