crowdsecurity/crowdsec · error
invalid path regex '%s' for bot entry '%s' in %s: %w
Error message
invalid path regex '%s' for bot entry '%s' in %s: %w
What it means
botFileInit compiles each element of the entry's optional "paths" array as a case-insensitive regex. This error is thrown when any individual path pattern fails regexp.Compile. Like the UA regex, paths are validated eagerly so a broken entry never reaches match time.
Source
Thrown at pkg/exprhelpers/botfile.go:77
return fmt.Errorf("missing mandatory 'name' field in %s: %s", filename, line)
}
if len(entry.IPs)+len(entry.Ranges)+len(entry.RDNS) == 0 {
return fmt.Errorf("bot entry '%s' in %s has no identity verification (need at least one of ips/ranges/rdns)", entry.Name, filename)
}
var err error
if entry.UserAgent != "" {
if entry.uaRegex, err = compileBotRegex(entry.UserAgent); err != nil {
return fmt.Errorf("invalid user_agent regex for bot entry '%s' in %s: %w", entry.Name, filename, err)
}
}
for _, p := range entry.Paths {
re, err := compileBotRegex(p)
if err != nil {
return fmt.Errorf("invalid path regex '%s' for bot entry '%s' in %s: %w", p, entry.Name, filename, err)
}
entry.pathRegexes = append(entry.pathRegexes, re)
}
entry.ipSet = make(map[netip.Addr]struct{}, len(entry.IPs))
for _, ip := range entry.IPs {
addr, err := netip.ParseAddr(ip)
if err != nil {
return fmt.Errorf("invalid IP '%s' for bot entry '%s' in %s: %w", ip, entry.Name, filename, err)
}
entry.ipSet[addr.Unmap()] = struct{}{}
}
for _, r := range entry.Ranges {
prefix, err := netip.ParsePrefix(r)View on GitHub (pinned to 909b515798)
Solutions
- Escape metacharacters in literal path text: "/search\?q=" instead of "/search?q=", "\.php" instead of ".php".
- Fix the syntax flaw the wrapped regexp/syntax error points to (unbalanced groups, dangling escapes, invalid repeat).
- Remove lookaheads/backreferences — Go's RE2 does not support them; restructure the pattern.
- Anchor patterns intentionally (^/admin) to avoid accidental broad matches once the regex compiles.
- Pre-compile each pattern with regexp.Compile in a scratch test before adding it to the data file.
Example fix
// before
{"name":"scanner","ips":["1.2.3.4"],"paths":["/wp-admin?section=("]}
// after
{"name":"scanner","ips":["1.2.3.4"],"paths":["^/wp-admin\\?.*"]} Defensive patterns
Strategy: validation
Validate before calling
for _, p := range entry.Paths {
if _, err := regexp.Compile("(?i)" + p); err != nil {
// reject the entry before FileInit
}
}
valid := err == nil Try / catch
if err := exprhelpers.FileInit(botFile, "bots"); err != nil {
if strings.Contains(err.Error(), "invalid path regex") {
log.Errorf("offending path pattern: %v", err) // message echoes the pattern
}
return err
} Prevention
- Escape ?, ., +, ( in literal URL text within path patterns.
- Anchor path regexes (^/admin) to keep matches precise.
- Test each path pattern against sample URLs with regexp.MatchString before deployment.
- Keep one pattern per array element; avoid overly complex combined patterns.
When it happens
Trigger: A bots JSONL entry has a "paths" array where one element is an invalid Go RE2 regex, e.g. "paths":["/wp-login*"] (invalid repetition after literal — actually valid as .*) — more precisely patterns like "/admin(" or "\\". The message names the offending pattern, entry name, and file.
Common situations: Writing URL paths with unescaped regex metacharacters (? in query strings, . matching any char, + in URLs); typos in hand-written patterns; porting PCRE path filters with unsupported RE2 constructs.
Related errors
- invalid user_agent regex for bot entry '%s' in %s: %w
- missing mandatory 'name' field in %s: %s
- bot entry '%s' in %s has no identity verification (need at l
- invalid IP '%s' for bot entry '%s' in %s: %w
- empty rdns pattern for bot entry '%s' in %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/bc513b2d4a90686e.
Report an issue: GitHub.