{"id":"5d7ddfc9910d4c46","repo":"BurntSushi/ripgrep","slug":"pattern-contains-byte-but-it-is-impossible-to","errorCode":null,"errorMessage":"pattern contains {byte:?} but it is impossible to match","messagePattern":"pattern contains (.+?) but it is impossible to match","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/regex/src/ban.rs","lineNumber":11,"sourceCode":"use regex_syntax::hir::{\n    self, ClassBytesRange, ClassUnicodeRange, Hir, HirKind,\n};\n\nuse crate::error::{Error, ErrorKind};\n\n/// Returns an error when a sub-expression in `expr` must match `byte`.\npub(crate) fn check(expr: &Hir, byte: u8) -> Result<(), Error> {\n    assert!(byte.is_ascii(), \"ban byte must be ASCII\");\n    let ch = char::from(byte);\n    let invalid = || Err(Error::new(ErrorKind::Banned(byte)));\n    match *expr.kind() {\n        HirKind::Empty => {}\n        HirKind::Literal(hir::Literal(ref lit)) => {\n            if lit.iter().find(|&&b| b == byte).is_some() {\n                return invalid();\n            }\n        }\n        HirKind::Class(hir::Class::Unicode(ref cls)) => {\n            if cls.ranges().iter().map(|r| r.len()).sum::<usize>() == 1 {\n                let contains =\n                    |r: &&ClassUnicodeRange| r.start() <= ch && ch <= r.end();\n                if cls.ranges().iter().find(contains).is_some() {\n                    return invalid();\n                }\n            }\n        }\n        HirKind::Class(hir::Class::Bytes(ref cls)) => {\n            if cls.ranges().iter().map(|r| r.len()).sum::<usize>() == 1 {","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/BurntSushi/ripgrep/blob/3fce3b5bb0236da2df6d99672afb8a719642eca7/crates/regex/src/ban.rs#L1-L29","documentation":"ban::check walks the regex HIR and returns ErrorKind::Banned(byte) when a sub-expression is forced to match a specific ASCII byte that has been banned (commonly NUL, 0x00, to keep searches line-oriented and avoid binary-data matches). The Display says the pattern contains that byte but it is impossible to match under the configured constraints. Banning only triggers for single-range classes or literals, not broad classes like [^\\x00].","triggerScenarios":"Building a regex with a configured banned byte (e.g. NUL) where the pattern contains a literal \\x00, a literal '\\n' when \\n is banned, or a singleton class like [\\x00] — i.e. the regex is compelled to match the banned byte.","commonSituations":"ripgrep banning NUL so that patterns do not match inside binary data; a pattern like \\x00 used to find NUL bytes that the searcher has been configured to forbid; copying a pattern from a context that allowed NUL into one that bans it.","solutions":["Remove the banned byte literal from the pattern (drop the \\x00 / \\n segment).","Use a negated or broader class so the byte is not compelled to match (e.g. [^\\x00] is allowed; [\\x00a] is also allowed because it is not a singleton).","Reconfigure the regex builder to not ban that byte if matching it is genuinely required."],"exampleFix":"// before\n// pattern \"\\x00\" with NUL banned -> Banned(0)\n\n// after\n// pattern \"[^\\x00]\" matches anything except NUL and is permitted","handlingStrategy":"validation","validationCode":"fn pattern_bans_byte(pat: &str, banned: u8) -> bool {\n    // crude check: literal \\xNN equal to banned byte appears as a singleton\n    let needle = format!(\"\\\\x{:02X}\", banned);\n    pat.contains(&needle)\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = regex::Regex::new(pat) {\n    eprintln!(\"{e}\"); // may be a banned byte\n}","preventionTips":["Avoid embedding the banned byte (often NUL) as a literal in patterns.","Use negated/broad classes ([^\\x00] or [\\x00a]) which are permitted.","If you must match the byte, reconfigure the builder to not ban it."],"tags":["regex","banned-byte","nul","binary"],"analyzedSha":"3fce3b5bb0236da2df6d99672afb8a719642eca7","analyzedAt":"2026-08-06T01:39:05.073Z","schemaVersion":2}