oxc-project/oxc · warning
Unexpected control characters
Error message
Unexpected control characters
What it means
Diagnostic from the oxlint rule `no-control-regex`, plural branch (crates/oxc_linter/src/rules/eslint/no_control_regex.rs:33). When a regular expression contains MORE THAN ONE control character (ASCII 0x00–0x1F plus 0x7F), the message is plural: 'Unexpected control characters'. Each match gets its own label showing the character as `\xNN`, `\uNNNN`, or `U+XXXX` when unprintable. Control characters in regexes are usually invisible paste artifacts and very hard to review; the help suggests using Unicode escapes if intentional.
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_control_regex.rs:33
.iter()
.map(|ch| {
let label = match ch.kind {
CharacterKind::Octal1 | CharacterKind::Octal2 | CharacterKind::Octal3 => {
format!(
"'{ch}' is a control character. It looks like a backreference, but there is no corresponding capture group."
)
}
_ => {
// Show the code point since the character itself is not printable
let ch = format!("U+{:04X}", ch.value);
format!("'{ch}' is a control character.")
}
};
ch.span.label(label)
})
.collect();
OxcDiagnostic::warn(if count > 1 {
"Unexpected control characters"
} else {
"Unexpected control character"
})
.with_help(
"Avoid matching control characters in regular expressions. If intentional, disable this rule for the expression.",
)
.with_labels(labels)
}
#[derive(Debug, Default, Clone)]
pub struct NoControlRegex;
declare_oxc_lint!(
/// ### What it does
///
/// Disallows control characters and some escape sequences that match
/// control characters in regular expressions.
///View on GitHub (pinned to 36ec0ef2ba)
Solutions
- If the control characters are accidental, retype the pattern so it contains only visible characters.
- If intentional, rewrite each control character as an explicit escape the rule accepts and that is reviewable — e.g. use a Unicode escape sequence (help text suggestion) such as /\u0000/ style, or match via `String.fromCharCode`-built patterns where appropriate.
- For terminal/ANSI handling prefer a dedicated library (e.g. ansi-regex) rather than hand-written control patterns.
- Suppress narrowly with `// oxlint-disable-next-line no-control-regex` on genuinely required control-character matching.
Example fix
// before const re = /[\x00-\x08\x0B\x0C\x0E-\x1F]+/; // multiple control chars // after const re = /[\t\r\n]+/; // whitelist the whitespace controls you mean
Defensive patterns
Strategy: validation
Validate before calling
// Gate: multiple control characters/escapes inside one regex literal const controlRuns = src.match(/\/[^\/\n]*\\x[01][0-9A-Fa-f][^\/\n]*\\x[01][0-9A-Fa-f][^\/\n]*\//g) || (src.match(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g) || []).length > 1 ? true : false;
Prevention
- Never paste regexes from terminals/packet dumps without re-typing control bytes.
- Express intentional control matching with visible escapes and inline suppression.
- Show invisibles in your editor when editing protocol-parsing regexes.
When it happens
Trigger: A regex literal or RegExp string containing 2+ control characters, raw or escaped — e.g. `const re = /\x00\x1F/;` matching NUL and US, or a pasted pattern embedding raw 0x0B/0x03 bytes. `count > 1` in the diagnostic constructor selects this plural message.
Common situations: Copy-pasting protocols/terminal escape patterns from documentation or packet dumps; parsing binary or serial-port logs; ANSI escape matching (\x1B sequences); files edited in editors that preserve invisible control bytes.
Related errors
- Unexpected control character
- Backreference '{back_reference}' will be ignored. It referen
- Backreference '{back_reference}' will be ignored. It referen
- Backreference '{back_reference}' will be ignored. It referen
- Unnecessary escape character {escape_char:?}
AI-assisted analysis of oxc-project/oxc@36ec0ef2ba (2026-08-20).
Data as JSON: /api/errors/0d6bdb283c72f065.
Report an issue: GitHub.