grafana/k6 · error
predicate must be a function
Error message
predicate must be a function
What it means
Thrown by parsePageWaitForEventOptions when the 'predicate' option of page.waitForEvent is present but sobek.AssertFunction fails — the value is not callable. k6 requires an actual function reference; strings of source code, bound-object property names, or plain objects are rejected.
Solutions
- Pass a real function reference: { predicate: r => r.ok() }.
- If building predicates from config data, construct a closure: const p = makePredicate(cfg); then { predicate: p }.
- Do not call the function when passing it (no trailing parentheses).
- Use an object-to-predicate adapter when config is data-only.
Example fix
// before
await page.waitForEvent('response', { predicate: cfg.predicateExpr }); // string from config
// after
const pred = new Function('r', 'return ' + cfg.predicateExpr);
await page.waitForEvent('response', { predicate: pred }); Defensive patterns
Strategy: type-guard
Validate before calling
if (opts.predicate !== undefined && typeof opts.predicate !== 'function') {
throw new TypeError('opts.predicate must be a function');
}
await page.waitForEvent('response', opts); Type guard
const hasCallablePredicate = (o) => o?.predicate === undefined || typeof o.predicate === 'function';
Prevention
- Pass function references, never strings of source code.
- Do not invoke the predicate when passing it (no trailing parentheses).
- When predicates come from external config, build closures with a factory function and typeof-check them.
When it happens
Trigger: page.waitForEvent('response', { predicate: 'r => r.ok()' }) (function as string); { predicate: { url: '/x' } } (object filter, unsupported in k6); passing result of calling the function instead of the function itself: { predicate: myPred() }.
Common situations: Translating Playwright's urlOrPredicate shorthand into a string; passing config-driven filter objects; accidentally invoking the function when passing it; JSON-serializing handlers from external config files.
Related errors
- executing waitForEvent predicate
- height must be a number, got
- parsing waitForEvent options
- predicate function is not callable
- waitForEvent does not support mapping for event
AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18).
Data as JSON: /api/errors/1aa4936d2fcfba07.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/page_mapping.go:1176
if k6common.IsNullish(opts) {
return ropts, nil, nil
}
if fn, ok := sobek.AssertFunction(opts); ok {
return ropts, fn, nil
}
obj := opts.ToObject(k6ext.Runtime(ctx))
var pred sobek.Callable
for _, k := range obj.Keys() {
switch k {
case "timeout":
ropts.Timeout = time.Duration(obj.Get(k).ToInteger()) * time.Millisecond
case "predicate":
fn, ok := sobek.AssertFunction(obj.Get(k))
if !ok {
return nil, nil, fmt.Errorf("predicate must be a function")
}
pred = fn
default:
return nil, nil, fmt.Errorf("waitForEvent does not support option: '%s'", k)
}
}
return ropts, pred, nil
}
// parseSize parses the size options from a Sobek value.
func parseSize(rt *sobek.Runtime, opts sobek.Value) (*common.Size, error) {
size := &common.Size{}
if k6common.IsNullish(opts) {
return size, nil
}
obj := opts.ToObject(rt)View on GitHub (pinned to 8d06114777)