grafana/k6 · error
predicate function is not callable
Error message
predicate function is not callable
What it means
browserContext.waitForEvent(event, optsOrPredicate) accepts either a bare predicate function or an options object `{ predicate, timeout }`. parseWaitForEventOptions (internal/js/modules/k6/browser/browser/browser_context_mapping.go:193-225) first tries sobek.AssertFunction on the whole argument; if that fails it treats it as an options object and requires that its `predicate` key be callable. Passing a `predicate` value that is not a function (string, number, object, undefined assigned explicitly) throws this error, mirroring Playwright's API contract.
Solutions
- Pass a real function: `waitForEvent('page', { predicate: (page) => page.url().includes('/home'), timeout: 10_000 })`
- Or pass the predicate directly without the options wrapper: `waitForEvent('page', (page) => !!page)`
- If the options come from JSON, keep only `timeout` there and attach the predicate in code: `const opts = { ...jsonOpts, predicate: myPredicate }`
Example fix
// before
const page = await browserContext.waitForEvent('page', {
predicate: 'page => page.url().includes("/order")',
});
// after
const page = await browserContext.waitForEvent('page', {
predicate: (page) => page.url().includes('/order'),
}); Defensive patterns
Strategy: type-guard
Validate before calling
const opts = { timeout: 10_000, predicate: config.predicate }; // config may come from data
if ('predicate' in opts && typeof opts.predicate !== 'function') {
throw new TypeError('waitForEvent: predicate must be a function, got ' + typeof opts.predicate);
}
const page = await browserContext.waitForEvent('page', opts); Type guard
const isPredicateFn = (v) => typeof v === 'function'; // usage: isPredicateFn(opts.predicate) — also covers omitting it entirely (undefined is simply skipped)
Try / catch
try {
const p = await browserContext.waitForEvent('page', opts);
} catch (e) {
if (String(e).includes('predicate function is not callable')) {
throw new Error('waitForEvent predicate was not a function — check how opts was built');
}
throw e;
} Prevention
- Never store predicates in JSON/config files — functions do not survive serialization; attach them in code
- Lint for quoted arrow functions in options objects (a common copy-paste slip)
- Pass the predicate directly as the second argument when no timeout customization is needed
- Keep Playwright docs open when porting examples: k6 mirrors the (event, optionsOrPredicate) signature
When it happens
Trigger: Calling `browserContext.waitForEvent('page', { predicate: 'page => page.url().includes("/x")' })` (predicate as a string), `waitForEvent('page', { predicate: null })`, or building the options object from data/config where the function got lost (JSON has no functions). Passing a non-callable, non-object value does NOT hit this branch — only an object containing a non-callable `predicate` key does.
Common situations: Copy-pasting Playwright examples but quoting the arrow function; storing options in JSON/data files where functions cannot survive serialization; refactoring an inline predicate into a variable that ends up undefined; passing `{ timeout: 5000, predicate: someObj.method }` where method was unbound and undefined.
Related errors
- executing waitForEvent predicate
- predicate must be a function
- steps must be an integer, got
- an error occurred communicating with k6 Cloud
- an error occurred communicating with the provisioning API
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/4c144991293f95b1.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/browser_context_mapping.go:215
Timeout: defaultTime,
}
if k6common.IsNullish(optsOrPredicate) {
return w, nil
}
var isCallable bool
w.PredicateFn, isCallable = sobek.AssertFunction(optsOrPredicate)
if isCallable {
return w, nil
}
opts := optsOrPredicate.ToObject(rt)
for _, k := range opts.Keys() {
switch k {
case "predicate":
w.PredicateFn, isCallable = sobek.AssertFunction(opts.Get(k))
if !isCallable {
return nil, errors.New("predicate function is not callable")
}
case "timeout":
w.Timeout = time.Duration(opts.Get(k).ToInteger()) * time.Millisecond
default:
return nil, fmt.Errorf("unknown option: %s", k)
}
}
return w, nil
}
View on GitHub (pinned to 01ffac6f24)