Regex: Lookbehind not supported
Lookbehind support is a property of the engine, not of the pattern: Go RE2 has none at all, Python and Java accept only fixed width lookbehinds, and JavaScript has supported the full form since ES2018. A pattern copied between languages therefore compiles in one and is rejected in the next.
Quick fix
Read the commands before running them. Anything that restarts a service, deletes data or changes permissions should be tried on a non-production system first.
# Who supports what, which decides whether the pattern can be kept at all
# JavaScript (ES2018+): variable width lookbehind, supported everywhere current
# .NET and the Python regex module: variable width
# Python re and Java: fixed width only, so quantifiers inside are rejected
# Go RE2, RE2 based engines and most SQL regex: no lookbehind or lookahead
// The portable rewrite: capture what you were looking behind, use group 1
// instead of: (?<=@)\w+
const m = "[email protected]".match(/@(\w+)/);
m[1]; // example
# Python: keep the lookbehind fixed, or capture instead
re.compile(r'(?<=Total: )\d+') # fine
re.compile(r'(?<=Total:\s*)\d+') # look-behind requires fixed-width pattern
// Go has no alternative syntax: match wider and filter in code
re := regexp.MustCompile(`@(\w+)`)
# Replacement is where lookbehind is least needed: a group keeps the prefix
re.sub(r'(Total: )\d+', r'\g<1>0', text)
How to diagnose Regex errors
Regex problems come in two flavours: it does not match what you expect (usually escaping, greediness, or an engine feature difference) and it matches but takes forever. The second is catastrophic backtracking, a genuine denial-of-service vector known as ReDoS, caused by nested quantifiers over overlapping character classes, such as (a+)+b. Any regex applied to untrusted input should be checked for it.
If the quick fix above does not resolve it, work through these steps. They apply to this whole class of error, not just to this one message, which is usually what saves the time.
- Test against a visualiser that shows backtracking steps, and always test with input that fails to match. That is where catastrophic backtracking appears, not on successful matches.
- Eliminate nested quantifiers over overlapping classes. Rewrite
(a+)+asa+, and prefer possessive quantifiers or atomic groups where the engine supports them. - Know your engine: lookbehind, named groups and Unicode property escapes differ between PCRE, RE2, JavaScript, Python and Go. RE2 (used by Go) deliberately has no backtracking and rejects some patterns outright.
- Anchor patterns with
^and$where you mean a whole-string match. Unanchored patterns silently match substrings. - Set a timeout or use a linear-time engine for user-supplied patterns. Never run an untrusted regex on a request thread.
Tools worth reaching for
regex101.comre2 / RE2JPython re.DEBUGgrep -P for PCRE testingrecheck / redos linters
Authoritative references
Primary documentation for this error, worth reading before applying any fix in production.
Related Regex errors
- Go: error parsing regexp: invalid or unsupported Perl syntax: (?!Go uses RE2, which has no backtracking and therefore no lookahead, no lookbehind and no…
- grep: Invalid range endA bracket expression contains a range whose end sorts before its start. In POSIX brackets a…
- Java: PatternSyntaxException: Dangling meta character '*' near index 0A quantifier such as *, + or ? appeared with nothing before it to repeat. It almost never…
- Java: PatternSyntaxException: Illegal repetitionA brace appears where the engine expects a quantifier, so a literal { in the pattern is read…
- JavaScript: Invalid regular expression: Duplicate capture group nameReusing a named group in different alternatives, as in (?\d{4})-\d{2}|\d{2}/(?\d{4}), only…
- Pattern attribute value [a-z-_]+ is not a valid regular expressionBrowsers now compile the HTML pattern attribute with the v (unicodeSets) flag, which is…
- Python: re.error: bad escape \d at position 0The replacement argument of re.sub is not a pattern. It understands only group references…
- Python: re.error: global flags not at the start of the expressionAn inline flag such as (?i) or (?s) appears somewhere other than the very start of the…
Browse other categories
- HTTP 494xx client errors, 5xx server errors, redirects, headers and protocol problems.
- JavaScript 42npm resolution, async pitfalls, hydration, memory limits and runtime type…
- Database 41Connections, deadlocks, constraints, replication and memory limits.
- AI 35Rate limits, context windows, GPU memory and model-serving failures.
- Network 35Refused connections, timeouts, resets, MTU problems and port exhaustion.
- Python 35Imports, virtual environments, encoding, concurrency and dependency conflicts.
- Kubernetes 34CrashLoopBackOff, ImagePullBackOff, OOMKilled, RBAC, scheduling and storage.
- Docker 27Daemon connectivity, disk space, image pulls, ports and architecture mismatches.
- System 26Disk space, systemd units, file descriptors, OOM killer and scheduled jobs.
- Cloud 25IAM permissions, quotas, service limits and credential failures.
- Security 25JWT validation, CSRF, OAuth grants, SELinux, SSH host keys and CSP.
- TLS 24Untrusted authorities, expiry, hostname mismatch, chains and cipher negotiation.
Something missing or wrong?
This entry is maintained by hand. If the fix is out of date, incomplete, or you have a better one, email a correction and it will be reviewed.