evanw/esbuild · error · Error
onResolve() call is missing a filter
Error message
onResolve() call is missing a filter
What it means
esbuild uses a RegExp 'filter' on every onResolve registration so the Go side can cheaply skip callbacks for irrelevant paths without crossing the JS↔Go boundary. At lib/shared/common.ts:1310 the registration throws if filter is null after getFlag(filter, mustBeRegExp) — mustBeRegExp requires value instanceof RegExp. Without a filter esbuild would have to call back for every single import, which destroys performance, so the field is mandatory.
Source
Thrown at lib/shared/common.ts:1310
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 6ff1d8b0d8)
Solutions
- Pass a RegExp: build.onResolve({ filter: /\.css$/ }, cb).
- Use /.*/ only as a last resort (it disables the perf optimisation); prefer a tight pattern.
- Remember the regex is matched against the unresolved path; escape dots: /\.css$/ not /.css$/.
Example fix
// before
build.onResolve({ filter: '*.css' }, args => { /* ... */ });
// after
build.onResolve({ filter: /\.css$/ }, args => { /* ... */ }); Defensive patterns
Strategy: type-guard
Validate before calling
function registerOnResolve(build, opts, cb) {
if (!(opts?.filter instanceof RegExp)) {
throw new TypeError('onResolve requires options.filter to be a RegExp');
}
build.onResolve(opts, cb);
} Type guard
function hasRegExpFilter(o): o is { filter: RegExp } {
return !!o && o.filter instanceof RegExp;
} Prevention
- Always pass filter as a RegExp literal — never a glob string.
- Scope the filter tightly for performance; /.*/ is a last resort.
- Escape literal dots: /\.css$/, not /.css$/.
When it happens
Trigger: build.onResolve({}, cb) — no filter. build.onResolve({ filter: './foo' }, cb) — string instead of RegExp. build.onResolve({ filter: /.*/ , namespace: undefined }) is fine, but forgetting filter entirely throws.
Common situations: Devs pass a glob string (e.g. '*.css') thinking esbuild supports glob syntax; it must be a RegExp. Misreading docs that show optional namespace and assuming filter is optional too. Object spread that drops filter.
Related errors
- onLoad() call is missing a filter
- Expected onResolve() callback in plugin ${quote(name)} to re
- Plugin at index ${i} must be an object
- Plugin at index ${i} is missing a name
- Plugin is missing a setup function
AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03).
Data as JSON: /data/errors/35cb325322428130.json.
Report an issue: GitHub.