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

  1. Point the client at a healthy, fully synced RPC endpoint (established provider or own synced node) and retry the wrap.
  2. Look the transaction hash up in a block explorer and confirm which block actually included it.
  3. If it recurs on a private chain, upgrade or reconfigure the node software so receipts carry correct block numbers.
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@d1527c24af (2026-08-21). Data as JSON: /api/errors/7bd403f83e1986d6. Report an issue: GitHub.