BurntSushi/ripgrep · error · Error
the literal {:?} is not allowed in a regex
Error message
the literal {:?} is not allowed in a regex What it means
strip_from_match removes the line-terminator byte from character classes where possible, but if a regex *must* match the line terminator as a literal (a bare literal, or a singleton/fully-stripped class), there is no safe rewrite and ErrorKind::NotAllowed(lit) is returned. The Display tells the user that literal is not allowed and (at the CLI layer) suggests enabling multiline mode (-U) so newlines can be matched.
Source
Thrown at crates/regex/src/strip.rs:60
) -> Result<Hir, Error> {
if line_term.is_crlf() {
let expr1 = strip_from_match_ascii(expr, b'\r')?;
strip_from_match_ascii(expr1, b'\n')
} else {
strip_from_match_ascii(expr, line_term.as_byte())
}
}
/// The implementation of strip_from_match. The given byte must be ASCII.
/// This function returns an error otherwise. It also returns an error if
/// it couldn't remove `\n` from the given regex without leaving an empty
/// character class in its place.
fn strip_from_match_ascii(expr: Hir, byte: u8) -> Result<Hir, Error> {
if !byte.is_ascii() {
return Err(Error::new(ErrorKind::InvalidLineTerminator(byte)));
}
let ch = char::from(byte);
let invalid = || Err(Error::new(ErrorKind::NotAllowed(ch.to_string())));
Ok(match expr.into_kind() {
HirKind::Empty => Hir::empty(),
HirKind::Literal(hir::Literal(lit)) => {
if lit.iter().find(|&&b| b == byte).is_some() {
return invalid();
}
Hir::literal(lit)
}
HirKind::Class(hir::Class::Unicode(mut cls)) => {
if cls.ranges().is_empty() {
return Ok(Hir::class(hir::Class::Unicode(cls)));
}
let remove = hir::ClassUnicode::new(Some(
hir::ClassUnicodeRange::new(ch, ch),
));
cls.difference(&remove);
if cls.ranges().is_empty() {
return invalid();View on GitHub (pinned to 3fce3b5bb0)
Solutions
- Enable multiline mode: use the -U/--multiline flag (or (?m) / (?s) in the pattern) so the line terminator can be matched.
- Remove the line-terminator literal from the pattern if you did not intend a multi-line match.
- Change the configured line terminator to a byte not used in your pattern.
Example fix
// before // $ rg 'foo\nbar' -> the literal '\n' is not allowed in a regex // after // $ rg -U 'foo\nbar' // multiline mode allows matching newlines
Defensive patterns
Strategy: validation
Validate before calling
fn needs_multiline(pat: &str, lt: u8) -> bool {
pat.contains(lt as char) || pat.contains(&format!("\\x{:02X}", lt))
} Try / catch
if let Err(e) = build_regex(pat, line_term) {
eprintln!("{e} -- try enabling multiline mode (-U)");
} Prevention
- Enable multiline mode (-U / (?m)) whenever a pattern is meant to span lines.
- Strip unintended line-terminator literals from generated patterns.
- Choose a line terminator byte that does not appear in your patterns.
When it happens
Trigger: Building a non-multiline regex whose pattern contains the line terminator as a literal — e.g. searching with default line terminator \n and a pattern like 'foo\nbar', '\n', '\x0A', or a class that reduces to only \n after stripping (e.g. [\n]).
Common situations: rg 'foo\nbar' without -U; a pattern intended to span lines written without enabling multiline mode; a generated pattern that embeds the record separator.
Related errors
- line terminators must be ASCII, but {byte:?} is not
- found invalid UTF-8 in pattern at byte offset {}: {} (disabl
- pattern contains {byte:?} but it is impossible to match
AI-assisted analysis of BurntSushi/ripgrep@3fce3b5bb0 (2026-08-06).
Data as JSON: /data/errors/24159c136cfc8164.json.
Report an issue: GitHub.