oxc-project/oxc · warning · OxcDiagnostic

Unnecessary escape character {escape_char:?}

Error message

Unnecessary escape character {escape_char:?}

What it means

Diagnostic from the `no-useless-escape` rule. A backslash precedes a character that has no special meaning in the current context (string literal, template literal, or regex), so the escape is noise. Oxc formats the character with `{:?}` so whitespace/control characters print safely and labels the exact escape span.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_useless_escape.rs:21

use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_regular_expression::{
    ast::{Character, CharacterClass},
    visit::{RegExpAstKind, Visit},
};
use oxc_semantic::NodeId;
use oxc_span::Span;
use schemars::JsonSchema;
use serde::Deserialize;

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
};

fn no_useless_escape_diagnostic(escape_char: char, span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("Unnecessary escape character {escape_char:?}")).with_label(span)
}

#[derive(Debug, Default, Clone, Deserialize)]
pub struct NoUselessEscape(Box<NoUselessEscapeConfig>);

impl std::ops::Deref for NoUselessEscape {
    type Target = NoUselessEscapeConfig;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoUselessEscapeConfig {
    /// An array of characters that are allowed to be escaped unnecessarily in regexes.
    /// For example, setting this to `["#"]` allows `\#` in regexes.

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Remove the backslash: `"\e"` -> `"e"`, `/a\-b/` -> `/a-b/`.
  2. Inside regex character classes, keep escapes only for class metacharacters (`]`, `\\`, `^`, `-`).
  3. If the literal must contain a real backslash, double it: `"\\d"` for a literal backslash-d.
  4. Use `oxlint --fix` to strip useless escapes automatically.

Example fix

// before
const s = "hel\lo";
const re = /\=/;

// after
const s = "hello";
const re = /=/;
Defensive patterns

Strategy: validation

Validate before calling

const hasUselessEscape = /\\([^nrtbfvxdDsSwWu0-9'`"\\\/\[\](){}^$.+*?|-])/g.test(literalRaw);

Prevention

When it happens

Trigger: Strings like `"\e"`, `'\#'`, or `"\'"` inside double quotes; regexes like `/\-/`, `/\%/` where the char is not a metacharacter. The rule inspects string/template/regex literal escape sequences and compares against characters that actually require escaping in that context.

Common situations: Over-escaped shell commands or grep patterns pasted into JS; regexes written for another flavor (e.g. `\-` needed inside character classes in some engines but not plain regex); code escaped for JSON or HTML then unescaped once too many.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/4ce7db0efb6e3e78. Report an issue: GitHub.