Skip to content

noUselessBackrefInRegex

Disallow useless backreferences in regular expression literals that always match an empty string.

A backreference refers to the submatch of a previous capturing group and matches the same text as that group. JavaScript regular expression support two syntaxes:

  • \N where N is a 1-based integer that refers to the N-th declared capturing group.
  • \k<name> that refers to the capturing group named name. This syntax is only available in Unicode-aware regular expressions, i.e. regular expressions using the u or v flag.

A backreference always matches an empty string when it refers to:

  • A group that belongs to another alternate branch. In /(a)|b\1b/, the group (a) and its backreference \1 are in distinct alternate branches. /(a)|b\1/ is equivalent to (a)|b/.

  • A group that appears after the backreference. In /\1(a)/, the group (a) is declared after its backreference \1. /\1(a)/ is equivalent to (a)/.

  • A group in which the backreference is declared. In /(\1)/, the backrefernce is nested in the group it refers to. /(\1)/ is equivalent to /()/.

  • A group that is inside a negative lookaround assertion without the backreference. In /a(?!(b)).\1/, the backrefernce is in a negative assertion while its backreference is outside. /a(?!(b)).\1/ is equivalent to /a(?!(b))./.

  • A group that is declared before the backreference inside a lookbehind assertion. In /(?<=(a)\1)b/, the backreference appears after the group while they are in a lookbehind assertion. /(?<=(a)\1)b/ is equivalent to /(?<=(a))b/.

A backreference that always matches an empty string is always successfully matched and is therefore useless.

/(a)|b\1/;
code-block.js:1:7 lint/nursery/noUselessBackrefInRegex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

This backreference refers to a group placed in another alternate branch, making it always match an empty string.

> 1 │ /(a)|b\1/;
^^
2 │

The backreference refers to this group.

> 1 │ /(a)|b\1/;
^^^
2 │

The alternate separator is here.

> 1 │ /(a)|b\1/;
^
2 │

Remove the backreference or place it in the same alternate branch as the group.

/\1(a)/;
code-block.js:1:2 lint/nursery/noUselessBackrefInRegex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

This backreference refers to a group that appears after it, making it always match an empty string.

> 1 │ /\1(a)/;
^^
2 │

A backreference must refer to a group defined before its occurrence.

Remove the backreference.

/(\1)/;
code-block.js:1:3 lint/nursery/noUselessBackrefInRegex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

This backreference is nested within the group to which it refers, making it always match an empty string.

> 1 │ /(\1)/;
^^
2 │

The group starts here.

> 1 │ /(\1)/;
^^^^
2 │

Remove the backreference or place it outside the group to which it refers.

/a(?!(b)).\1/;
code-block.js:1:11 lint/nursery/noUselessBackrefInRegex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

This backreference refers to a group within a negated assertion, making it always match an empty string.

> 1 │ /a(?!(b)).\1/;
^^
2 │

The backreference refers to this group.

> 1 │ /a(?!(b)).\1/;
^^^
2 │

The negated assertion is here.

> 1 │ /a(?!(b)).\1/;
^^^
2 │

Remove the backreference or place it in the negated assertion.

/(?<=(a)\1)b/;
code-block.js:1:9 lint/nursery/noUselessBackrefInRegex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

This backreference refers to a group that appears before itself in a lookbehind assertion, making it always match an empty string.

> 1 │ /(?<=(a)\1)b/;
^^
2 │

The backreference refers to this group.

> 1 │ /(?<=(a)\1)b/;
^^^
2 │

The lookbehind assertion is here.

> 1 │ /(?<=(a)\1)b/;
^^^^
2 │

Remove the backreference or place it after the group it refers to.

/(a)\1/;
/(?<foo>a)\k<foo>/u;
/a(?!(b|c)\1)./;
biome.json
{
"linter": {
"rules": {
"nursery": {
"noUselessBackrefInRegex": "error"
}
}
}
}