What the error means
Before a regular expression can match anything, the engine compiles it. Invalid regular expression: /.../: <reason> is JavaScript's compile-time failure: the pattern violates the grammar, so no matching is attempted at all. The part after the colon is the useful bit — Unterminated group, Unmatched ')', Nothing to repeat, Invalid escape, Unterminated character class, Invalid flags — and it names the specific rule that was broken.
In the example, the second group opens with ( and never closes, so the reason is Unterminated group.
Why it happens
- Unbalanced brackets. A
(without), a[without], or a{that starts a quantifier and never closes. Easy to do when editing a long pattern by hand. - Nothing to repeat. A quantifier with nothing before it: a pattern that starts with
*or+, or a group like(?+). Alsoa**, two quantifiers in a row. - A literal special character.
.,+,?,(,[,{,|,^,$,\all have meaning. Matching a literal(requires\(; matching1.5literally requires1\.5. - A bad escape.
\p{Letter}without theuflag, or\k<name>referring to a group that does not exist. - Invalid or duplicate flags, such as
ggor a flag the engine does not support. - Pattern copied from another language. Python's
(?P<name>...), PCRE's possessivea++, and.NET's(?<name>...)with different lookbehind rules do not all translate to JavaScript.
How to fix it
- Paste the pattern into the tester above. The error card repeats the engine's reason; read the words after the colon.
- For unbalanced brackets, count them, or format the pattern with one group per line in your head: every
(needs a). - For "nothing to repeat", find the quantifier at the start of the pattern or group and either remove it or give it something to repeat.
- For a literal special character, prefix it with
\. String Escape in regex mode escapes a whole literal string at once, which is safer than doing it by eye. - Compile again. Once the pattern is valid, the match table shows what it captures.
The corrected example:
(\d{3})-(\d{4})
If it still fails
- A pattern built from user input needs escaping before it becomes a regex; a stray
(from the user produces exactly this error at runtime. - If the pattern is valid but slow or never returns, that is a different problem — see Catastrophic backtracking.
- Regex Generator builds common patterns (emails, dates, IPs) with the escaping already correct, which is a faster starting point than a blank editor.