{"record":{"id":"081149a55754b2f2","repo":"grafana/k6","slug":"evaluating-handle-for-frame-execution-context-q","errorCode":null,"errorMessage":"evaluating handle for frame: execution context %q not found","messagePattern":"evaluating handle for frame: execution context %q not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/frame.go","lineNumber":911,"sourceCode":"\t}\n\tif exceptionDetails != nil {\n\t\treturn fmt.Errorf(\"%s\", parseExceptionDetails(exceptionDetails))\n\t}\n\n\treturn nil\n}\n\n// EvaluateHandle will evaluate provided page function within an execution context.\nfunc (f *Frame) EvaluateHandle(pageFunc string, args ...any) (handle JSHandleAPI, _ error) {\n\tf.log.Debugf(\"Frame:EvaluateHandle\", \"fid:%s furl:%q\", f.ID(), f.URL())\n\n\tevalHandle := func() (JSHandleAPI, error) {\n\t\tf.executionContextMu.RLock()\n\t\tdefer f.executionContextMu.RUnlock()\n\n\t\tec := f.executionContexts[mainWorld]\n\t\tif ec == nil {\n\t\t\treturn nil, fmt.Errorf(\"evaluating handle for frame: execution context %q not found\", mainWorld)\n\t\t}\n\t\treturn ec.EvalHandle(f.ctx, pageFunc, args...) //nolint:wrapcheck\n\t}\n\n\tf.waitForExecutionContext(mainWorld)\n\thandle, err := evalHandle()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"evaluating handle for frame: %w\", err)\n\t}\n\n\tapplySlowMo(f.ctx)\n\n\treturn handle, nil\n}\n\n// Fill fills out the first element found that matches the selector.\nfunc (f *Frame) Fill(selector, value string, popts *FrameFillOptions) error {\n\tf.log.Debugf(\"Frame:Fill\", \"fid:%s furl:%q sel:%q val:%q\", f.ID(), f.URL(), selector, value)","sourceCodeStart":893,"sourceCodeEnd":929,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/frame.go#L893-L929","documentation":"Frame.EvaluateHandle() waits for the main-world execution context, then looks it up under f.executionContexts[mainWorld]. If the map entry is still nil after the wait (context destroyed by navigation, frame detached, or context creation racing), this error is returned. The waitForExecutionContext call right above shows the module already tried to let the context appear.","triggerScenarios":"Calling EvaluateHandle immediately after page.goto()/frame creation before the main world is created; the frame navigates so the previous context is nulled and the new one has not registered; the frame (iframe) gets detached.","commonSituations":"Early-script races on about:blank; redirect chains nulling contexts; OOPIF iframes with slow context creation; heavy parallelism slowing context registration.","solutions":["Wait for a concrete document state first: await page.waitForLoadState('domcontentloaded') before EvaluateHandle.","Retry once after a short delay — the context usually registers immediately after.","If working in an iframe, obtain the frame after it is attached and wait on it."],"exampleFix":"// before\nconst h = page.evaluateHandle('() => window'); // right after goto, main world missing\n\n// after\nawait page.waitForLoadState('domcontentloaded');\nconst h = page.evaluateHandle('() => window');","handlingStrategy":"retry","validationCode":"await page.waitForLoadState('domcontentloaded');","typeGuard":null,"tryCatchPattern":"let h;\nfor (let i = 0; i < 3; i++) {\n  try { h = page.evaluateHandle(pageFunc); break; } catch (e) { await sleep(500); }\n}\nif (!h) throw new Error('evaluateHandle failed: no execution context');","preventionTips":["Wait for domcontentloaded before handle evaluation.","Expect context churn around redirects; retry once.","Prefer waitForSelector over raw evaluateHandle for element access."],"tags":["browser","evaluate-handle","execution-context","navigation","race-condition"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}