evanw/esbuild · error
[%s] %q filter is not a valid Go regular expression: %q
Error message
[%s] %q filter is not a valid Go regular expression: %q
What it means
Returned by config.CompileFilterForPlugin when a plugin's OnResolve/OnLoad filter is a non-empty string that fails Go's regexp.Compile (RE2 syntax). esbuild precompiles filters for performance and caches them, so a syntactically bad regex is caught at plugin-registration time. The offending filter is echoed in the message.
Source
Thrown at internal/config/config.go:763
// Cache for next time
filterMutex.Lock()
defer filterMutex.Unlock()
if filterCache == nil {
filterCache = make(map[string]*regexp.Regexp)
}
filterCache[filter] = result
return
}
func CompileFilterForPlugin(pluginName string, kind string, filter string) (*regexp.Regexp, error) {
if filter == "" {
return nil, fmt.Errorf("[%s] %q is missing a filter", pluginName, kind)
}
result := compileFilter(filter)
if result == nil {
return nil, fmt.Errorf("[%s] %q filter is not a valid Go regular expression: %q", pluginName, kind, filter)
}
return result, nil
}
func PluginAppliesToPath(path logger.Path, filter *regexp.Regexp, namespace string) bool {
return (namespace == "" || path.Namespace == namespace) && filter.MatchString(path.Text)
}
////////////////////////////////////////////////////////////////////////////////
// Plugin API
type Plugin struct {
Name string
OnStart []OnStart
OnResolve []OnResolve
OnLoad []OnLoad
}View on GitHub (pinned to 6ff1d8b0d8)
Solutions
- Rewrite the regex in RE2-compatible syntax (no lookahead, no lookbehind, no backreferences).
- Test the pattern with Go's regexp playground or `regexp.Compile` before passing it as a filter.
- If you need lookahead semantics, move that logic inside the callback and use a broader filter.
- Validate filter strings at plugin-author time with a unit test that compiles them.
Example fix
// before
b.onResolve({ filter: 'foo(?=bar)' }, fn) // lookahead unsupported by RE2
// after
b.onResolve({ filter: 'foobar' }, fn) // match literally; or do lookahead inside fn Defensive patterns
Strategy: validation
Validate before calling
// Pre-compile the filter with Go-compatible RE2 semantics where possible.
// In Node there is no RE2 by default, but you can at least sanity-check balance:
function looksLikeBalancedRegex(s) {
let depth = 0
for (const ch of s) {
if (ch === '(') depth++
if (ch === ')') depth--
if (depth < 0) return false
}
return depth === 0
}
if (!looksLikeBalancedRegex(filter)) throw new Error('Filter looks unbalanced: ' + filter) Type guard
function isSafeEsbuildFilter(s: string): boolean {
return s.length > 0 && !/(\(\?<=)|(\(\?=)|(\(\?!)|(\(\?<!)|\\\d)/.test(s)
} Try / catch
try {
await esbuild.build({ plugins })
} catch (e) {
if (/not a valid Go regular expression/i.test(e.message)) {
console.error('Plugin filter is not RE2-compatible:', e.message)
// identify the offending plugin via the bracketed [name] prefix
}
throw e
} Prevention
- Avoid lookahead/lookbehind/backreferences in esbuild plugin filters.
- Keep filters minimal — match a file extension or namespace, not a complex expression.
- Unit-test filters against Go regexp.Compile (e.g. via a tiny Go helper or the 're2' npm package) in CI.
When it happens
Trigger: Pass a filter containing PCRE-only constructs unsupported by RE2 (e.g. lookahead '(?=...)', backreferences, or an unbalanced parenthesis). Examples: filter: 'foo(bar', filter: '(?<=x)', filter: '[z-a]' (invalid range). Fires for OnResolve and OnLoad registrations in JS or Go plugin setup.
Common situations: Copying a JavaScript RegExp literal into the filter string that uses lookbehind/lookahead (JS supports these, Go RE2 does not); pasting a regex from a Stack Overflow answer that uses backreferences; version differences where a previously-tolerant engine accepted the pattern but RE2 rejects it.
Related errors
- [%s] %q is missing a filter
- onResolve() call is missing a filter
- onLoad() call is missing a filter
- The service was stopped
- Invalid path suffix %q returned from plugin (must start with
AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03).
Data as JSON: /data/errors/306d1a9a1d5a4384.json.
Report an issue: GitHub.