unionlabs/union · error · anyhow::Error

send_ibc_transaction failed: {:?}

Error message

send_ibc_transaction failed: {:?}

What it means

Top-level wrapper in union-test's e2e driver (`send_and_recv`): it calls `source_chain.send_ibc_transaction(...)` (EVM or Cosmos implementation depending on chain type) and re-wraps any failure with this message. The real cause is always the attached inner error printed with `{:?}`.

Source

Thrown at tools/union-test/src/lib.rs:698

    pub async fn send_and_recv<Src: ChainEndpoint, Dst: ChainEndpoint>(
        &self,
        source_chain: &Src,
        contract: Src::Contract,
        msg: Src::Msg,
        destination_chain: &Dst,
        timeout: Duration,
        signer: &Src::ProviderType,
    ) -> anyhow::Result<helpers::PacketRecv> {
        let (packet_hash, _height) = match source_chain
            .send_ibc_transaction(contract.clone(), msg.clone(), signer)
            .await
        {
            Ok(hash) => {
                println!("send_ibc_tx succeeded with hash: {:?}", hash);
                hash
            }
            Err(e) => {
                anyhow::bail!("send_ibc_transaction failed: {:?}", e);
            }
        };
        println!(
            "Packet sent from {} to {} with hash: {}",
            source_chain.chain_id(),
            destination_chain.chain_id(),
            packet_hash
        );
        match destination_chain
            .wait_for_packet_recv(packet_hash, timeout)
            .await
        {
            Ok(evt) => Ok(evt),
            Err(e) => anyhow::bail!("wait_for_packet_recv failed: {:?}", e),
        }
    }

    pub async fn send_and_recv_and_ack<Src: ChainEndpoint, Dst: ChainEndpoint>(

View on GitHub (pinned to 031785bb6d)

Solutions

  1. Read the inner error in the bail message and fix that specific cause (funds, sequence, RPC, msg encoding)
  2. If the inner cause is transient (sequence mismatch, RPC hiccup), wait briefly and re-run the test
  3. Verify the source chain signer and contract addresses in the fixture

Example fix

// before
suite.send_and_recv(src, contract, msg, dst, Duration::from_secs(120), &signer).await?; 
// after: one retry for transient source-side send failures
let r = suite.send_and_recv(src, contract, msg.clone(), dst, Duration::from_secs(120), &signer).await;
let recv = match r {
    Err(e) if is_transient_send_err(&e) => {
        tokio::time::sleep(Duration::from_secs(10)).await;
        suite.send_and_recv(src, contract, msg, dst, Duration::from_secs(120), &signer).await?
    }
    r => r?,
};
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: source signer can broadcast (cosmos: sequence settles; evm: funds present)
let _ = source_chain.get_fee_payer_balance().await?; // fails fast on setup issues

Try / catch

match suite.send_and_recv(src, contract, msg.clone(), dst, timeout, &signer).await {
    Ok(r) => Ok(r),
    Err(e) if e.to_string().starts_with("send_ibc_transaction failed") && is_transient(&e) => {
        tokio::time::sleep(Duration::from_secs(10)).await;
        suite.send_and_recv(src, contract, msg, dst, timeout, &signer).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Any failure of the underlying send: cosmos sequence-mismatch exhaustion ('failed to send transaction'), missing wasm-packet_send event, missing tx height, or on EVM a keyring/RPC broadcast failure. In all cases the packet never left the source chain.

Common situations: Unfunded or mis-sequenced signer; msg encoding that doesn't produce a packet; RPC issues on the source chain — anything that makes the source-side send step of an e2e test fail.

Related errors


AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16). Data as JSON: /api/errors/2e6310fc1fbcf832. Report an issue: GitHub.