grafana/k6 · error
evaluateHandle requires a page function
Error message
evaluateHandle requires a page function
What it means
Thrown synchronously when Frame.evaluateHandle is called without a usable page function — the same sobekEmptyString guard as evaluate: the first argument must not be null/undefined or a blank/whitespace-only string. evaluateHandle returns a JSHandle to the expression's result, but the argument contract is identical to evaluate.
Solutions
- Pass a function or non-empty string first: frame.evaluateHandle(() => document.body)
- Validate dynamically-built expressions before calling
- Remember the remaining arguments are arg... for the function, not options
Example fix
// before
const h = await frame.evaluateHandle(fn); // fn is undefined
// after
if (typeof fn !== 'function' && !(typeof fn === 'string' && fn.trim())) {
throw new Error('evaluateHandle requires a page function');
}
const h = await frame.evaluateHandle(fn); Defensive patterns
Strategy: validation
Validate before calling
function usablePageFunc(v) {
return typeof v === 'function' || (typeof v === 'string' && v.trim() !== '');
}
if (!usablePageFunc(fn)) throw new Error('evaluateHandle requires a non-empty function or expression string');
await frame.evaluateHandle(fn, ...args); Type guard
function isPageFunction(v) {
return typeof v === 'function' || (typeof v !== 'object' && v != null && String(v).trim() !== '');
} Try / catch
try {
const h = await frame.evaluateHandle(fn);
return h;
} catch (e) {
if (String(e).includes('evaluateHandle requires a page function')) {
return await frame.evaluateHandle('undefined'); // explicit no-op handle
}
throw e;
} Prevention
- Apply the same non-empty guard you use for evaluate()
- Remember evaluateHandle's extra arguments are function args, not options
- Unit-test expression builders so they can never emit blank strings
When it happens
Trigger: frame.evaluateHandle(), frame.evaluateHandle(''), frame.evaluateHandle(' '), or passing a variable that resolves to undefined/null/empty string.
Common situations: Copy-paste from an evaluate() call where the function argument was lost; passing a handle or options object in the first slot instead of a function; empty expression from string interpolation.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- evaluate requires a page function
- missing required argument 'altText'
- missing required argument 'label'
- missing required argument 'placeholder'
- missing required argument 'role'
AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18).
Data as JSON: /api/errors/51b2a283deec12c9.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/frame_mapping.go:84
}
earg := exportArg(eventInit)
return promise(vu, func() (any, error) {
return nil, f.DispatchEvent(selector, typ, earg, popts) //nolint:wrapcheck
}), nil
},
"evaluate": func(pageFunc sobek.Value, gargs ...sobek.Value) (*sobek.Promise, error) {
if sobekEmptyString(pageFunc) {
return nil, fmt.Errorf("evaluate requires a page function")
}
funcString := pageFunc.String()
gopts := exportArgs(gargs)
return promise(vu, func() (any, error) {
return f.Evaluate(funcString, gopts...)
}), nil
},
"evaluateHandle": func(pageFunc sobek.Value, gargs ...sobek.Value) (*sobek.Promise, error) {
if sobekEmptyString(pageFunc) {
return nil, fmt.Errorf("evaluateHandle requires a page function")
}
funcString := pageFunc.String()
gopts := exportArgs(gargs)
return promise(vu, func() (any, error) {
jsh, err := f.EvaluateHandle(funcString, gopts...)
if err != nil {
return nil, err //nolint:wrapcheck
}
return mapJSHandle(vu, jsh), nil
}), nil
},
"fill": func(selector, value string, opts sobek.Value) (*sobek.Promise, error) {
popts, err := parseFrameFillOptions(rt, opts, f.Timeout())
if err != nil {
return nil, fmt.Errorf("parsing fill options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, f.Fill(selector, value, popts) //nolint:wrapcheckView on GitHub (pinned to 8d06114777)