unionlabs/union · warning · anyhow::Error

regex matched but capture group missing

Error message

regex matched but capture group missing

What it means

A defensive, effectively unreachable branch in send_and_expect_revert: Regex::captures succeeded (so group 1 exists by construction of the regex (0x[0-9A-Fa-f]+), which has exactly one capturing group), yet caps.get(1) returned None and the code bails with 'regex matched but capture group missing'. In practice you should never see this; hitting it indicates a regex crate version/behavior anomaly or corrupted logic.

Source

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

                "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())
                    .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,

View on GitHub (pinned to 031785bb6d)

Solutions

  1. If encountered, check whether the regex literal near lib.rs:1042 was modified to use optional/non-participating groups; restore a single mandatory group.
  2. Simplify by using re.captures(...).and_then(|c| c.get(1)) and treating both as the 111 case, removing the impossible branch.
  3. Verify regex crate version in Cargo.lock is the one the code was written for.
Defensive patterns

Strategy: type-guard

Type guard

fn first_capture(caps: &regex::Captures<'_>) -> Option<&str> {
    caps.get(1).map(|m| m.as_str()) // single mandatory group always participates
}

Prevention

When it happens

Trigger: Only producible if the regex pattern were edited to include an optional capture group that did not participate in the match, or an incompatible regex crate regression — the current pattern always populates group 1 on a match.

Common situations: Someone modifies the regex to (0x...)?-style optional groups; pathological regex crate downgrade/upgrade. Otherwise this is dead defensive code.

Related errors


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