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

  1. Pass a function or non-empty string first: frame.evaluateHandle(() => document.body)
  2. Validate dynamically-built expressions before calling
  3. 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

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


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:wrapcheck

View on GitHub (pinned to 8d06114777)