{"record":{"id":"e87b528bfb050dc8","repo":"unionlabs/union","slug":"expected-revert-0x-08x-but-transaction-succeede","errorCode":null,"errorMessage":"Expected revert 0x{:08x}, but transaction succeeded","messagePattern":"Expected revert 0x(.+?), but transaction succeeded","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"tools/union-test/src/lib.rs","lineNumber":1027,"sourceCode":"        };\n        println!(\"Update client event received: {:?}\", update_client_result);\n\n        Ok(update_client_result.unwrap().height)\n    }\n\n    pub async fn send_and_expect_revert<Src: ChainEndpoint, Dst: ChainEndpoint>(\n        &self,\n        source_chain: &Src,\n        contract: Src::Contract,\n        msg: Src::Msg,\n        expected_revert_code: u32,\n        signer: &Src::ProviderType,\n    ) -> anyhow::Result<()> {\n        match source_chain\n            .send_ibc_transaction(contract.clone(), msg.clone(), signer)\n            .await\n        {\n            Ok((_, _)) => anyhow::bail!(\n                \"Expected revert 0x{:08x}, but transaction succeeded\",\n                expected_revert_code\n            ),\n\n            Err(e) => {\n                let err_str = format!(\"{:#}\", e);\n\n                let re = Regex::new(r\"(0x[0-9A-Fa-f]+)\").unwrap();\n                let caps = re.captures(&err_str).ok_or_else(|| {\n                    anyhow!(\n                        \"Transaction reverted but no rawValue hex found: {}\",\n                        err_str\n                    )\n                })?;\n\n                let hex_full = caps\n                    .get(1)\n                    .map(|m| m.as_str())","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/tools/union-test/src/lib.rs#L1009-L1045","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: contract was changed to succeed on this path\ntw.send_and_expect_revert(&src, contract, msg, EXPECTED_REVERT, &signer).await?;\n\n// after: assert the now-successful path\ntw.send_and_recv_ack(&src, contract, msg, &dst, timeout, &signer).await?;","handlingStrategy":"validation","validationCode":"// confirm the precondition that makes the branch revert before asserting it\nlet bal = contract.balance_of(signer.address()).await?;\nanyhow::ensure!(bal < amount, \"balance covers amount — this path will succeed, not revert\");","typeGuard":null,"tryCatchPattern":"match tw.send_and_expect_revert(&src, contract, msg, code, &signer).await {\n    Err(e) if e.to_string().contains(\"transaction succeeded\") => { /* precondition lost: re-establish it and retry once */ }\n    other => other?,\n}","preventionTips":["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."],"tags":["ibc","rust","revert","assertion","test-harness"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}