unionlabs/union · error

rawValue too short for a selector: {}

Error message

rawValue too short for a selector: {}

What it means

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.

Source

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

            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())
                    .ok_or_else(|| anyhow!("regex matched but capture group missing"))?;

                let hexdigits = hex_full.trim_start_matches("0x");
                if hexdigits.len() < 8 {
                    anyhow::bail!("rawValue too short for a selector: {}", hex_full);
                }
                let selector_hex = &hexdigits[..8]; // first 4 bytes

                let actual = u32::from_str_radix(selector_hex, 16).with_context(|| {
                    format!("parsing revert selector `{selector_hex}` from `{hex_full}`")
                })?;

                if actual == expected_revert_code {
                    Ok(())
                } else {
                    anyhow::bail!(
                        "Expected selector 0x{:08x}, got 0x{:08x} (raw: {})",
                        expected_revert_code,
                        actual,
                        hex_full
                    )
                }
            }

View on GitHub (pinned to 031785bb6d)

Solutions

  1. Look at the raw error string in the message: identify what the short hex actually is and whether the real selector appears later.
  2. 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.
  3. Tighten the regex to require at least 8 hex digits, e.g. (0x[0-9A-Fa-f]{8,}), so short tokens are skipped.
  4. Update the contract test fixture to revert with a proper custom error selector.

Example fix

// before — matches any hex token, including 2-char ones
let re = Regex::new(r"(0x[0-9A-Fa-f]+)").unwrap();

// after — only selector-shaped hex can match
let re = Regex::new(r"(0x[0-9A-Fa-f]{8,})").unwrap();
Defensive patterns

Strategy: validation

Validate before calling

// pre-check shape before slicing
anyhow::ensure!(hexdigits.len() >= 8, "raw value {hex_full} has no selector ({} hex digits)", hexdigits.len());

Type guard

fn is_selector_shaped(hex_full: &str) -> bool {
    let d = hex_full.trim_start_matches("0x");
    !d.is_empty() && d.chars().all(|c| c.is_ascii_hexdigit()) && d.len() >= 8
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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