{"record":{"id":"51b2a283deec12c9","repo":"grafana/k6","slug":"evaluatehandle-requires-a-page-function","errorCode":null,"errorMessage":"evaluateHandle requires a page function","messagePattern":"evaluateHandle requires a page function","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/frame_mapping.go","lineNumber":84,"sourceCode":"\t\t\t}\n\t\t\tearg := exportArg(eventInit)\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn nil, f.DispatchEvent(selector, typ, earg, popts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"evaluate\": func(pageFunc sobek.Value, gargs ...sobek.Value) (*sobek.Promise, error) {\n\t\t\tif sobekEmptyString(pageFunc) {\n\t\t\t\treturn nil, fmt.Errorf(\"evaluate requires a page function\")\n\t\t\t}\n\t\t\tfuncString := pageFunc.String()\n\t\t\tgopts := exportArgs(gargs)\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn f.Evaluate(funcString, gopts...)\n\t\t\t}), nil\n\t\t},\n\t\t\"evaluateHandle\": func(pageFunc sobek.Value, gargs ...sobek.Value) (*sobek.Promise, error) {\n\t\t\tif sobekEmptyString(pageFunc) {\n\t\t\t\treturn nil, fmt.Errorf(\"evaluateHandle requires a page function\")\n\t\t\t}\n\t\t\tfuncString := pageFunc.String()\n\t\t\tgopts := exportArgs(gargs)\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\tjsh, err := f.EvaluateHandle(funcString, gopts...)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err //nolint:wrapcheck\n\t\t\t\t}\n\t\t\t\treturn mapJSHandle(vu, jsh), nil\n\t\t\t}), nil\n\t\t},\n\t\t\"fill\": func(selector, value string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts, err := parseFrameFillOptions(rt, opts, f.Timeout())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing fill options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn nil, f.Fill(selector, value, popts) //nolint:wrapcheck","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/grafana/k6/blob/8d06114777191d21ef885d05c5f8aa9e1ed838ae/internal/js/modules/k6/browser/browser/frame_mapping.go#L66-L102","documentation":"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.","triggerScenarios":"frame.evaluateHandle(), frame.evaluateHandle(''), frame.evaluateHandle('  '), or passing a variable that resolves to undefined/null/empty string.","commonSituations":"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.","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"],"exampleFix":"// before\nconst h = await frame.evaluateHandle(fn); // fn is undefined\n// after\nif (typeof fn !== 'function' && !(typeof fn === 'string' && fn.trim())) {\n  throw new Error('evaluateHandle requires a page function');\n}\nconst h = await frame.evaluateHandle(fn);","handlingStrategy":"validation","validationCode":"function usablePageFunc(v) {\n  return typeof v === 'function' || (typeof v === 'string' && v.trim() !== '');\n}\nif (!usablePageFunc(fn)) throw new Error('evaluateHandle requires a non-empty function or expression string');\nawait frame.evaluateHandle(fn, ...args);","typeGuard":"function isPageFunction(v) {\n  return typeof v === 'function' || (typeof v !== 'object' && v != null && String(v).trim() !== '');\n}","tryCatchPattern":"try {\n  const h = await frame.evaluateHandle(fn);\n  return h;\n} catch (e) {\n  if (String(e).includes('evaluateHandle requires a page function')) {\n    return await frame.evaluateHandle('undefined'); // explicit no-op handle\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["k6","browser","frame","evaluatehandle","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"8d06114777191d21ef885d05c5f8aa9e1ed838ae","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}