evanw/esbuild · error · Error
onResolve() call is missing a filter
Error message
onResolve() call is missing a filter
What it means
When a plugin registers an `onResolve` callback (lib/shared/common.ts:1314), esbuild reads `options.filter` with `mustBeRegExp` and throws if it is null/undefined. The filter is a RegExp that limits which import paths this callback handles; it is required because the resolver is performance-sensitive and must avoid invoking every plugin for every path.
Solutions
- Pass a `filter` RegExp, e.g. `build.onResolve({ filter: /^node:path$/ }, cb)`.
- To match all paths use `/.*/`, but prefer a tighter filter for performance.
- Ensure the value is a RegExp literal or `new RegExp(...)`, not a string.
Example fix
// before
build.onResolve({ namespace: 'ns' }, args => { ... });
// after
build.onResolve({ filter: /.*/, namespace: 'ns' }, args => { ... }); Defensive patterns
Strategy: validation
Validate before calling
function registerOnResolve(build, opts, cb) {
if (!(opts.filter instanceof RegExp)) throw new Error('onResolve requires a filter RegExp');
build.onResolve(opts, cb);
} Type guard
function hasOnResolveFilter(o: any): o is { filter: RegExp } {
return !!o && o.filter instanceof RegExp;
} Prevention
- Always pass a RegExp literal as filter.
- Tighten filters to improve build performance.
When it happens
Trigger: Calling `build.onResolve({}, callback)` or `build.onResolve({ namespace: 'x' }, callback)` without supplying a `filter` RegExp.
Common situations: Forgetting the filter; passing a string filter instead of a RegExp; assuming esbuild matches everything by default.
Related errors
- Expected onResolve() callback in plugin
- Must specify "kind" when calling "resolve"
- onLoad() call is missing a filter
- Plugin at index must be an object
- Cannot call "resolve" before plugin setup has completed
AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09).
Data as JSON: /api/errors/35cb325322428130.
Report an issue: GitHub.
Appendix: source
Thrown at lib/shared/common.ts:1314
onStartCallbacks.push({ name: name!, callback, note: registeredNote })
plugin.onStart = true
},
onEnd(callback) {
let registeredText = `This error came from the "onEnd" callback registered here:`
let registeredNote = extractCallerV8(new Error(registeredText), streamIn, 'onEnd')
onEndCallbacks.push({ name: name!, callback, note: registeredNote })
plugin.onEnd = true
},
onResolve(options, callback) {
let registeredText = `This error came from the "onResolve" callback registered here:`
let registeredNote = extractCallerV8(new Error(registeredText), streamIn, 'onResolve')
let keys: OptionKeys = {}
let filter = getFlag(options, keys, 'filter', mustBeRegExp)
let namespace = getFlag(options, keys, 'namespace', mustBeString)
checkForInvalidFlags(options, keys, `in onResolve() call for plugin ${quote(name)}`)
if (filter == null) throw new Error(`onResolve() call is missing a filter`)
let id = nextCallbackID++
onResolveCallbacks[id] = { name: name!, callback, note: registeredNote }
plugin.onResolve.push({ id, filter: jsRegExpToGoRegExp(filter), namespace: namespace || '' })
},
onLoad(options, callback) {
let registeredText = `This error came from the "onLoad" callback registered here:`
let registeredNote = extractCallerV8(new Error(registeredText), streamIn, 'onLoad')
let keys: OptionKeys = {}
let filter = getFlag(options, keys, 'filter', mustBeRegExp)
let namespace = getFlag(options, keys, 'namespace', mustBeString)
checkForInvalidFlags(options, keys, `in onLoad() call for plugin ${quote(name)}`)
if (filter == null) throw new Error(`onLoad() call is missing a filter`)
let id = nextCallbackID++
onLoadCallbacks[id] = { name: name!, callback, note: registeredNote }
plugin.onLoad.push({ id, filter: jsRegExpToGoRegExp(filter), namespace: namespace || '' })
},
View on GitHub (pinned to f6058f8364)