oxc-project/oxc · error · OxcDiagnostic

Invalid regular expression: `u` and `v` flags should be used

Error message

Invalid regular expression: `u` and `v` flags should be used alone

What it means

Diagnostic from oxlint's eslint/no-invalid-regexp rule (crates/oxc_linter/src/rules/eslint/no_invalid_regexp.rs:31). The 'u' (unicode) and 'v' (unicodeSets) modes are mutually exclusive parsing modes, so specifying both (/x/uv or new RegExp('x', 'uv')) is a SyntaxError per the ECMAScript spec. The label explains which of the two flags must be dropped based on which one was specified first.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_invalid_regexp.rs:31

    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
};

// Use the same prefix with `oxc_regular_expression` crate
fn duplicated_flag_diagnostic(span: Span, flag: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn("Invalid regular expression: Duplicated flag")
        .with_help(format!("Remove the duplicated '{flag}' flag from the regular expression flags"))
        .with_label(span.label(format!("flag '{flag}' already specified")))
}

fn unknown_flag_diagnostic(span: Span, flag: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn("Invalid regular expression: Unknown flag")
        .with_note("Valid flags are: d (indices), g (global), i (ignore case), m (multiline),\n             s (dot all), u (unicode), v (unicode sets), y (sticky)")
        .with_label(span.label(format!("flag '{flag}' is not a valid regular expression flag")))
}

fn invalid_unicode_flags_diagnostic(span: Span, is_u_specified: bool) -> OxcDiagnostic {
    OxcDiagnostic::warn("Invalid regular expression: `u` and `v` flags should be used alone")
        .with_help("Specify only one of 'u' or 'v' flags")
        .with_label(span.label(if is_u_specified {
            "the 'v' flag cannot be used when the 'u' flag is specified"
        } else {
            "the 'u' flag cannot be used when the 'v' flag is specified"
        }))
}

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

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow invalid regular expression strings in RegExp constructors.
    ///
    /// ### Why is this bad?
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Keep exactly one of the two: drop 'u' and keep 'v' when you need [\q{...}] strings, set subtraction/intersection, or nested classes; keep 'u' for plain unicode mode
  2. Remember 'v' is a superset of 'u' features, so /x/v alone is usually what you want when upgrading
  3. Check flags strings assembled from constants for accidental inclusion of both letters

Example fix

// before
const re = /[\q{abc}]/uv;
const re2 = new RegExp('x', 'uv');

// after
const re = /[\q{abc}]/v;
const re2 = new RegExp('x', 'v');
Defensive patterns

Strategy: validation

Validate before calling

function assertUvExclusive(flags) {
  if (flags.includes('u') && flags.includes('v')) {
    throw new RangeError("'u' and 'v' regex flags are mutually exclusive");
  }
}
assertUvExclusive(modeFlags);
const re = new RegExp(pattern, modeFlags);

Type guard

function isUvCompatible(flags) {
  return !(flags.includes('u') && flags.includes('v'));
}

Try / catch

try {
  new RegExp(pattern, flags);
} catch (e) {
  if (e instanceof SyntaxError && /u.*v|v.*u/i.test(e.message)) {
    flags = flags.replace('u', ''); // keep v as the superset and retry
    re = new RegExp(pattern, flags);
  }
}

Prevention

When it happens

Trigger: A regex literal with both flags: /[\q{a}]/uv or /x/uv; a RegExp constructor call with 'uv' or 'vu' as the flags string. This often happens when adding the newer 'v' flag to a regex that already carried 'u'.

Common situations: Migrating a 'u'-flag regex to 'v' for set operations (difference, intersection, string literals in classes) and forgetting to delete 'u'; copy-pasting a 'v'-mode pattern like [\q{ab}] into code whose flags string still says 'u'; enabling both flags 'to be safe'.

Related errors


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