{"record":{"id":"7876fa85ae467d55","repo":"PyO3/pyo3","slug":"invalid-hex-encoding","errorCode":null,"errorMessage":"invalid hex encoding","messagePattern":"invalid hex encoding","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pyo3-build-config/src/impl_.rs","lineNumber":2700,"sourceCode":"\n        escaped.push(LUT[(byte >> 4) as usize] as char);\n        escaped.push(LUT[(byte & 0x0F) as usize] as char);\n    }\n\n    escaped\n}\n\nfn unescape(escaped: &str) -> Vec<u8> {\n    assert_eq!(escaped.len() % 2, 0, \"invalid hex encoding\");\n\n    let mut bytes = Vec::with_capacity(escaped.len() / 2);\n\n    for chunk in escaped.as_bytes().chunks_exact(2) {\n        fn unhex(hex: u8) -> u8 {\n            match hex {\n                b'a'..=b'f' => hex - b'a' + 10,\n                b'0'..=b'9' => hex - b'0',\n                _ => panic!(\"invalid hex encoding\"),\n            }\n        }\n\n        bytes.push((unhex(chunk[0]) << 4) | unhex(chunk[1]));\n    }\n\n    bytes\n}\n\n#[cfg(test)]\n// can remove this expect when fields are private\n#[expect(deprecated, reason = \"accessing config fields directly for testing\")]\nmod tests {\n    use target_lexicon::triple;\n\n    use super::*;\n\n    #[test]","sourceCodeStart":2682,"sourceCodeEnd":2718,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/pyo3-build-config/src/impl_.rs#L2682-L2718","documentation":"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.","triggerScenarios":"An environment/config value routed through pyo3_build_script_impl contains a non-hexadecimal character where two hex digits are expected during unescaping.","commonSituations":"Corrupted or hand-edited config/env values passed into the build script; library version mismatch where the producer encoded differently than this decoder expects.","solutions":["Fix the input value so it only contains lowercase hex pairs [0-9a-f]","Clear and re-set the offending env/config variables (e.g. via cargo clean and a clean environment)","Upgrade or align pyo3 crate versions so encoder and decoder match"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn is_valid_hex_pairs(s: &str) -> bool {\n    s.len() % 2 == 0 && s.bytes().all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only pass values produced by pyo3's own escaping code into build-script env vars","Clean the build environment (cargo clean) when upgrading pyo3","Align all pyo3-* crate versions in the dependency tree"],"tags":["build-script","hex-decoding","panic"],"backgroundTag":"invalid-hex-encoding","analyzedSha":"ac9b6899d348be4d54614d060dea53a645a12e36","analyzedAt":"2026-09-05T09:20:35.319Z","contentChangedAt":"2026-09-05T09:20:35.319Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}