projectdiscovery/nuclei · error

could not compile regex: %s

Error message

could not compile regex: %s

What it means

Template compilation error from Matcher.CompileMatchers (pkg/operators/matchers/compile.go:53). Each entry of the matcher's `regex:` list is compiled with the stdlib RE2 regexp.Compile (with a shared cache). Unparseable patterns abort matcher compilation with the offending pattern.

Source

Thrown at pkg/operators/matchers/compile.go:53

	// Validate the matcher structure
	if err := matcher.Validate(); err != nil {
		return err
	}

	// By default, match on body if user hasn't provided any specific items
	if matcher.Part == "" && matcher.GetType() != DSLMatcher {
		matcher.Part = "body"
	}

	// Compile the regexes (with shared cache)
	for _, regex := range matcher.Regex {
		if cached, err := cache.Regex().GetIFPresent(regex); err == nil && cached != nil {
			matcher.regexCompiled = append(matcher.regexCompiled, cached)
			continue
		}
		compiled, err := regexp.Compile(regex)
		if err != nil {
			return fmt.Errorf("could not compile regex: %s", regex)
		}
		_ = cache.Regex().Set(regex, compiled)
		matcher.regexCompiled = append(matcher.regexCompiled, compiled)
	}

	// Compile and validate binary Values in matcher
	for _, value := range matcher.Binary {
		if decoded, err := hex.DecodeString(value); err != nil {
			return fmt.Errorf("could not hex decode binary: %s", value)
		} else {
			matcher.binaryDecoded = append(matcher.binaryDecoded, string(decoded))
		}
	}

	// Compile the dsl expressions (with shared cache)
	for _, dslExpression := range matcher.DSL {
		if cached, err := cache.DSL().GetIFPresent(dslExpression); err == nil && cached != nil {
			matcher.dslCompiled = append(matcher.dslCompiled, cached)

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Test each regex with Go's RE2 engine (regex101 'golang' flavor) and fix/remove unsupported constructs
  2. In YAML prefer single-quoted strings so \d, \s, \+ pass through verbatim
  3. When a regex is composed from variables, escape interpolated values (regexp.QuoteMeta equivalent in DSL: `re_quote` if available, or precompute)
  4. Run `nuclei -validate -t template.yaml` to get the exact failing pattern

Example fix

# before
regex:
  - '(?<=v)1\.\d+'
# after
regex:
  - 'v(1\.\d+)'
Defensive patterns

Strategy: validation

Validate before calling

for _, r := range m.Regex {
	if _, err := regexp.Compile(r); err != nil {
		return fmt.Errorf("bad matcher regex %q: %w", r, err)
	}
}

Type guard

func matcherRegexCompiles(pattern string) bool { _, err := regexp.Compile(pattern); return err == nil }

Try / catch

if err := m.CompileMatchers(); err != nil && strings.Contains(err.Error(), "could not compile regex") {
	// pull pattern from message; flag RE2 incompatibility (backrefs/lookarounds)
}

Prevention

When it happens

Trigger: A matcher regex containing PCRE-only constructs (backreferences \1, lookarounds (?=...) (?<=...)) or syntax errors such as unbalanced parens, a dangling '*', or an invalid escape.

Common situations: Copying detection regexes written for PCRE (Snort/ModSecurity/Python rules) into templates; YAML double-quote escaping eating backslashes ("\d" becomes literal 'd' issues); partially rendered dynamic regexes (e.g. payloads with regex metachars).

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/8e435f5b07be83ef. Report an issue: GitHub.