{"record":{"id":"d0d83796afab1028","repo":"grafana/k6","slug":"nil-result","errorCode":null,"errorMessage":"nil result","messagePattern":"nil result","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/execution_context.go","lineNumber":329,"sourceCode":"\n// EvalHandle evaluates the provided JavaScript within this execution context\n// and returns a JSHandle.\nfunc (e *ExecutionContext) EvalHandle(apiCtx context.Context, js string, args ...any) (JSHandleAPI, error) {\n\tif escapesSobekValues(args...) {\n\t\treturn nil, errors.New(\"sobek.Value escaped\")\n\t}\n\topts := evalOptions{\n\t\tforceCallable: true,\n\t\treturnByValue: false,\n\t}\n\tevalArgs := make([]any, 0, len(args))\n\tevalArgs = append(evalArgs, args...)\n\tres, err := e.eval(apiCtx, opts, js, evalArgs...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif res == nil {\n\t\treturn nil, errors.New(\"nil result\")\n\t}\n\n\tr, ok := res.(JSHandleAPI)\n\tif !ok {\n\t\treturn nil, ErrJSHandleInvalid\n\t}\n\n\treturn r, nil\n}\n\n// Frame returns the frame that this execution context belongs to.\nfunc (e *ExecutionContext) Frame() *Frame {\n\treturn e.frame\n}\n\n// ID returns the CDP runtime ID of this execution context.\nfunc (e *ExecutionContext) ID() runtime.ExecutionContextID {\n\treturn e.id","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/js/modules/k6/browser/common/execution_context.go#L311-L347","documentation":"ExecutionContext.EvalHandle (execution_context.go:314-338) backs page.evaluateHandle/frame.evaluateHandle. The CDP evaluation itself succeeded, but it produced no remote-object result (the expression returned null or undefined), so there is nothing to wrap in a JSHandle and k6 returns 'nil result'.","triggerScenarios":"page.evaluateHandle(() => null); evaluateHandle('document.getElementById(\"does-not-exist\")') (querySelector miss returns null); an arrow function with a body that has no return statement (implicit undefined).","commonSituations":"Querying handles for optional/conditional elements; typos in ids or selectors used inside the expression; code ported from page.$ where the miss would instead return null cleanly.","solutions":["Use page.$(selector) / frame.$(selector) for element lookups — they return null instead of erroring","Make the evaluated function always return a real object or element (e.g. document.querySelector(sel) || ({}))","If you only need a value, not a handle, use page.evaluate and null-check the result","Guard for null inside the page function and return a sentinel object you check afterwards"],"exampleFix":"// before\nconst h = await page.evaluateHandle(() => document.getElementById('missing'));\n\n// after\nconst h = await page.$('#missing'); // null, no throw\nif (!h) throw new Error('element #missing not found');","handlingStrategy":"try-catch","validationCode":"// Prefer $ for element lookups; null instead of throw\nconst h = await page.$('#maybe-missing');\nif (h === null) {\n  // handle absence explicitly\n}","typeGuard":"// Guard evaluateHandle results inside the page function\nconst h = await page.evaluateHandle(\n  () => document.querySelector('#x') || { missing: true }\n);\nconst props = await h.getProperties();\nif (props.get('missing')) { /* absent */ }","tryCatchPattern":"try {\n  const h = await page.evaluateHandle(fn);\n} catch (e) {\n  if (/nil result/.test(e.message)) {\n    // expression returned null/undefined — treat as missing\n  } else throw e;\n}","preventionTips":["Use page.$ for DOM lookups; reserve evaluateHandle for JS values you know exist","Make evaluated functions return a sentinel object on miss","Check that the expression has an explicit return statement"],"tags":["browser","evaluatehandle","null","cdp"],"backgroundTag":"evaluate-returned-null","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}