{"record":{"id":"0e5a024f56cdaf9b","repo":"unionlabs/union","slug":"rawvalue-too-short-for-a-selector","errorCode":null,"errorMessage":"rawValue too short for a selector: {}","messagePattern":"rawValue too short for a selector: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/union-test/src/lib.rs","lineNumber":1050,"sourceCode":"            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())\n                    .ok_or_else(|| anyhow!(\"regex matched but capture group missing\"))?;\n\n                let hexdigits = hex_full.trim_start_matches(\"0x\");\n                if hexdigits.len() < 8 {\n                    anyhow::bail!(\"rawValue too short for a selector: {}\", hex_full);\n                }\n                let selector_hex = &hexdigits[..8]; // first 4 bytes\n\n                let actual = u32::from_str_radix(selector_hex, 16).with_context(|| {\n                    format!(\"parsing revert selector `{selector_hex}` from `{hex_full}`\")\n                })?;\n\n                if actual == expected_revert_code {\n                    Ok(())\n                } else {\n                    anyhow::bail!(\n                        \"Expected selector 0x{:08x}, got 0x{:08x} (raw: {})\",\n                        expected_revert_code,\n                        actual,\n                        hex_full\n                    )\n                }\n            }","sourceCodeStart":1032,"sourceCodeEnd":1068,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/tools/union-test/src/lib.rs#L1032-L1068","documentation":"send_and_expect_revert extracted a hex string from the revert error, but after stripping 0x it holds fewer than 8 hex digits (4 bytes), the minimum length of a Solidity revert selector. The transaction did revert, but the captured hex is not selector-shaped (e.g. a short rawValue like 0x01 or a non-selector hex fragment matched earlier in the error string), so the first-4-bytes selector comparison is meaningless and the helper bails.","triggerScenarios":"Contract reverts via require with a bare short value (common: 0x00/0x01 flags) instead of a custom Error(string)/selector; or the regex matched a short incidental hex token (address of 1-2 chars never, but gas values like 0x1f can appear) before the real rawValue; revert with empty data plus stray short hex in the message.","commonSituations":"Cosmos-wasm style contract errors surfaced as short hex codes; minimal require(cond) reverts with no message; provider error text containing a small hex number (e.g. block 0x5) that the greedy regex grabs first.","solutions":["Look at the raw error string in the message: identify what the short hex actually is and whether the real selector appears later.","If the contract genuinely reverts with a short code, don't use send_and_expect_revert's selector matching — assert on the raw value or use a different check.","Tighten the regex to require at least 8 hex digits, e.g. (0x[0-9A-Fa-f]{8,}), so short tokens are skipped.","Update the contract test fixture to revert with a proper custom error selector."],"exampleFix":"// before — matches any hex token, including 2-char ones\nlet re = Regex::new(r\"(0x[0-9A-Fa-f]+)\").unwrap();\n\n// after — only selector-shaped hex can match\nlet re = Regex::new(r\"(0x[0-9A-Fa-f]{8,})\").unwrap();","handlingStrategy":"validation","validationCode":"// pre-check shape before slicing\nanyhow::ensure!(hexdigits.len() >= 8, \"raw value {hex_full} has no selector ({} hex digits)\", hexdigits.len());","typeGuard":"fn is_selector_shaped(hex_full: &str) -> bool {\n    let d = hex_full.trim_start_matches(\"0x\");\n    !d.is_empty() && d.chars().all(|c| c.is_ascii_hexdigit()) && d.len() >= 8\n}","tryCatchPattern":null,"preventionTips":["Require {8,} hex digits in the regex so short flags/gas values never match.","Make contracts revert with custom errors (4-byte selectors) in tests rather than bare require flags."],"tags":["ibc","rust","revert","selector","regex"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}