unionlabs/union · error · anyhow::Error

wait_for_packet_recv failed: {:?}

Error message

wait_for_packet_recv failed: {:?}

What it means

After a successful packet send, `send_and_recv` waits on `destination_chain.wait_for_packet_recv(packet_hash, timeout)`; this error means the receiving chain did not observe a packet-recv event for that hash within the timeout. Almost always a relaying/latency problem, not a code failure.

Source

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

                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>(
        &self,
        source_chain: &Src,
        contract: Src::Contract,
        msg: Src::Msg,
        destination_chain: &Dst,
        timeout: Duration,
        signer: &Src::ProviderType,
    ) -> anyhow::Result<(helpers::PacketRecv, helpers::PacketAck)> {
        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);

View on GitHub (pinned to 031785bb6d)

Solutions

  1. Increase the `timeout` passed to send_and_recv
  2. Check that the relayer is running and healthy between the two chains
  3. Verify the IBC client/channel are open and not expired or errored
  4. Confirm the destination chain is producing blocks

Example fix

// before
suite.send_and_recv(src, c, m, dst, Duration::from_secs(120), &signer).await?; 
// after
suite.send_and_recv(src, c, m, dst, Duration::from_secs(900), &signer).await?;
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: relayer reachable / channels open before waiting for recv
let _ = destination_chain.query_channel_end(&port_id, &channel_id).await?; // errors early if the path is broken

Try / catch

match suite.send_and_recv(src, c, m.clone(), dst, timeout, &signer).await {
    Ok(r) => Ok(r),
    Err(e) if e.to_string().contains("wait_for_packet_recv failed") => {
        check_repeater_health();
        suite.send_and_recv(src, c, m, dst, timeout * 2, &signer).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Relayer between the chains stopped or slow; destination chain halted; timeout shorter than relayer latency plus proof-verification time; broken/expired client or channel so the relayer skips the packet.

Common situations: Devnet relayer process not started; timeouts tuned for fast local chains reused on slower testnets; client expiry after chain downtime.

Related errors


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