PyO3/pyo3 · error

invalid hex encoding

Error message

invalid hex encoding

What it means

Assertion inside the hex-decoding helper unescape() used to round-trip mangled symbol/identifier names in the build config. The input string was produced by escaping every byte as two hex characters, so its length must be even; an odd-length (or otherwise corrupt) escaped string fails this length invariant before any byte is decoded.

Source

Thrown at pyo3-build-config/src/impl_.rs:2700

        escaped.push(LUT[(byte >> 4) as usize] as char);
        escaped.push(LUT[(byte & 0x0F) as usize] as char);
    }

    escaped
}

fn unescape(escaped: &str) -> Vec<u8> {
    assert_eq!(escaped.len() % 2, 0, "invalid hex encoding");

    let mut bytes = Vec::with_capacity(escaped.len() / 2);

    for chunk in escaped.as_bytes().chunks_exact(2) {
        fn unhex(hex: u8) -> u8 {
            match hex {
                b'a'..=b'f' => hex - b'a' + 10,
                b'0'..=b'9' => hex - b'0',
                _ => panic!("invalid hex encoding"),
            }
        }

        bytes.push((unhex(chunk[0]) << 4) | unhex(chunk[1]));
    }

    bytes
}

#[cfg(test)]
// can remove this expect when fields are private
#[expect(deprecated, reason = "accessing config fields directly for testing")]
mod tests {
    use target_lexicon::triple;

    use super::*;

    #[test]

View on GitHub (pinned to ac9b6899d3)

Solutions

  1. Fix the input value so it only contains lowercase hex pairs [0-9a-f]
  2. Clear and re-set the offending env/config variables (e.g. via cargo clean and a clean environment)
  3. Upgrade or align pyo3 crate versions so encoder and decoder match
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_hex_pairs(s: &str) -> bool {
    s.len() % 2 == 0 && s.bytes().all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))
}

Prevention

When it happens

Trigger: An environment/config value routed through pyo3_build_script_impl contains a non-hexadecimal character where two hex digits are expected during unescaping.

Common situations: Corrupted or hand-edited config/env values passed into the build script; library version mismatch where the producer encoded differently than this decoder expects.

Related errors


AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05). Data as JSON: /api/errors/7876fa85ae467d55. Report an issue: GitHub.