unionlabs/union · error · anyhow::Error
Expected revert 0x{:08x}, but transaction succeeded
Error message
Expected revert 0x{:08x}, but transaction succeeded What it means
send_and_expect_revert deliberately sends a tx that should fail on-chain and then matches the revert selector against expected_revert_code. This error means the opposite happened: send_ibc_transaction returned Ok, i.e. the transaction succeeded (or at least was accepted) when the test asserted a specific revert. Either the contract logic changed so the path no longer reverts, or the test set the wrong expectation.
Source
Thrown at tools/union-test/src/lib.rs:1027
};
println!("Update client event received: {:?}", update_client_result);
Ok(update_client_result.unwrap().height)
}
pub async fn send_and_expect_revert<Src: ChainEndpoint, Dst: ChainEndpoint>(
&self,
source_chain: &Src,
contract: Src::Contract,
msg: Src::Msg,
expected_revert_code: u32,
signer: &Src::ProviderType,
) -> anyhow::Result<()> {
match source_chain
.send_ibc_transaction(contract.clone(), msg.clone(), signer)
.await
{
Ok((_, _)) => anyhow::bail!(
"Expected revert 0x{:08x}, but transaction succeeded",
expected_revert_code
),
Err(e) => {
let err_str = format!("{:#}", e);
let re = Regex::new(r"(0x[0-9A-Fa-f]+)").unwrap();
let caps = re.captures(&err_str).ok_or_else(|| {
anyhow!(
"Transaction reverted but no rawValue hex found: {}",
err_str
)
})?;
let hex_full = caps
.get(1)
.map(|m| m.as_str())View on GitHub (pinned to 031785bb6d)
Solutions
- Decide whether the tx should now succeed: if the contract behavior intentionally changed, switch to the success-path helper (send_and_recv_ack) instead of expecting a revert.
- If a revert is still expected, reproduce the exact precondition that triggers it (drain the balance, remove the channel, etc.) before the call.
- Recompute expected_revert_code from the current contract's error selector table (keccak of the error signature's first 4 bytes).
- Check you are testing the right contract address / build artifacts.
Example fix
// before: contract was changed to succeed on this path tw.send_and_expect_revert(&src, contract, msg, EXPECTED_REVERT, &signer).await?; // after: assert the now-successful path tw.send_and_recv_ack(&src, contract, msg, &dst, timeout, &signer).await?;
Defensive patterns
Strategy: validation
Validate before calling
// confirm the precondition that makes the branch revert before asserting it let bal = contract.balance_of(signer.address()).await?; anyhow::ensure!(bal < amount, "balance covers amount — this path will succeed, not revert");
Try / catch
match tw.send_and_expect_revert(&src, contract, msg, code, &signer).await {
Err(e) if e.to_string().contains("transaction succeeded") => { /* precondition lost: re-establish it and retry once */ }
other => other?,
} Prevention
- Establish revert preconditions explicitly at test start and assert them before the send.
- Derive expected selectors from the current ABI, never hard-code stale u32 constants.
When it happens
Trigger: Calling send_and_expect_revert with expected_revert_code for a branch the contract no longer reverts on (guard conditions changed, fixture state different), or passing a msg that hits a success path — e.g. transfer that now succeeds because balances were topped up by a previous test.
Common situations: Contract upgrade removes/changes a revert; shared test-chain state (funds arrived, channel created) invalidating the assumption of failure; wrong msg constructed so it takes the happy path; expected selector computed from a stale ABI.
Related errors
- Expected selector 0x{:08x}, got 0x{:08x} (raw: {})
- wait_for_packet_timeout failed: {:?}
- Transaction reverted but no rawValue hex found: {}
- rawValue too short for a selector: {}
- not implemented
AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16).
Data as JSON: /api/errors/e87b528bfb050dc8.
Report an issue: GitHub.