grafana/k6 · error
predicate function is not callable
Error message
predicate function is not callable
What it means
browserContext.waitForEvent accepts either a bare predicate function or an options object; in the object form the `predicate` member must itself be callable. parseWaitForEventOptions uses sobek.AssertFunction, which fails for numbers, strings, undefined, or non-function values (browser_context_mapping.go:215).
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 93accf6570)
Solutions
- Pass the function reference, not its result: `{ predicate: (page) => page.url().includes('x') }`
- Or pass the predicate directly as the second arg: `waitForEvent('page', (page) => ...)`
- Keep `timeout` (ms, number) as the only other key in the object form
Example fix
// before
const page = await context.waitForEvent('page', { predicate: isTargetPage() });
// after
const page = await context.waitForEvent('page', { predicate: isTargetPage }); Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the options object before calling waitForEvent
function isWaitForEventOpts(v) {
if (typeof v === 'function') return true;
if (v === null || typeof v !== 'object') return false;
const keys = Object.keys(v);
return keys.every((k) => k === 'predicate' || k === 'timeout') &&
(v.predicate === undefined || typeof v.predicate === 'function') &&
(v.timeout === undefined || typeof v.timeout === 'number');
} Type guard
const isPredicateCallable = (o) => o == null || typeof o === 'function' || typeof o.predicate === 'function';
Try / catch
try {
const page = await context.waitForEvent('page', { predicate: isTargetPage, timeout: 30_000 });
} catch (e) {
if (/predicate function is not callable/.test(e.message)) throw new TypeError('waitForEvent: pass the function reference, not its return value');
throw e;
} Prevention
- Pass function references (`isTargetPage`), never invocations (`isTargetPage()`)
- Only `predicate` and `timeout` are accepted keys — selectors/strings are not supported
- Model options on Playwright's waitForEvent but remember k6 requires a real callable predicate
When it happens
Trigger: `context.waitForEvent('page', { predicate: fn() })` — invoking the function and passing its return value; `{ predicate: 'selector' }`; `{ predicate: undefined }`; also any unknown key in the object form yields the sibling 'unknown option' error.
Common situations: Copy-pasting Playwright examples where strings are accepted; accidentally executing the predicate while wiring it; refactoring the predicate into a value.
Related errors
- empty gRPC client
- unknown browser event: %q, must be %q
- exported 'setup' must be a function
- exported 'teardown' must be a function
- no exported functions in script
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/4c144991293f95b1.
Report an issue: GitHub.