{"record":{"id":"1f2ccedb4d2e1813","repo":"grafana/k6","slug":"does-not-have-a-frame-owner","errorCode":null,"errorMessage":"does not have a frame owner","messagePattern":"does not have a frame owner","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/execution_context.go","lineNumber":141,"sourceCode":"\t\tesid target.SessionID\n\t)\n\tif eh.frame != nil {\n\t\tefid = cdp.FrameID(eh.frame.ID())\n\t}\n\tif eh.session != nil {\n\t\tesid = eh.session.ID()\n\t}\n\te.logger.Debugf(\n\t\t\"ExecutionContext:adoptElementHandle\",\n\t\t\"sid:%s stid:%s fid:%s ectxid:%d furl:%q ehtid:%s ehsid:%s\",\n\t\te.sid, e.stid, e.fid, e.id, e.furl,\n\t\tefid, esid)\n\n\tif eh.execCtx == e {\n\t\treturn nil, errors.New(\"already belongs to the same execution context\")\n\t}\n\tif e.frame == nil {\n\t\treturn nil, errors.New(\"does not have a frame owner\")\n\t}\n\n\tvar node *cdp.Node\n\tvar err error\n\n\taction := dom.DescribeNode().WithObjectID(eh.remoteObject.ObjectID)\n\tif node, err = action.Do(cdp.WithExecutor(e.ctx, e.session)); err != nil {\n\t\treturn nil, fmt.Errorf(\"describing DOM node: %w\", err)\n\t}\n\n\treturn e.adoptBackendNodeID(node.BackendNodeID)\n}\n\n// eval evaluates the provided JavaScript within this execution context and\n// returns a value or handle.\n//\n//nolint:funlen\nfunc (e *ExecutionContext) eval(","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/js/modules/k6/browser/common/execution_context.go#L123-L159","documentation":"Also from adoptElementHandle (execution_context.go:138-141): the destination ExecutionContext has frame == nil, meaning it is not bound to any frame (a page-level or already-destroyed context). An element adopted into such a context could never be attached to a document, so k6 refuses the operation.","triggerScenarios":"Adopting a handle into a context whose frame was detached during navigation; a context obtained from a popup or iframe that has since closed; racing a page navigation so the context's frame was cleared before adoption ran.","commonSituations":"Heavy SPA navigation while holding element handles; iframes removed from the DOM mid-wait; contexts captured before navigation and reused after it completes.","solutions":["Re-acquire the frame and re-query the element after navigation settles (waitForNavigation + fresh page.$)","Wait for a stable state (page.waitForLoadState('load')) before DOM operations that adopt or transfer handles","Drop pre-navigation handles: dispose them and query anew on the current frame","Wrap the operation in try-catch and retry once with fresh objects — the old context will never recover"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Stabilize before DOM operations that transfer handles\nawait page.waitForLoadState('load');\nconst frame = page.frames().find(f => f.name() === 'app');\nif (!frame) throw new Error('frame not (yet) available');","typeGuard":null,"tryCatchPattern":"try {\n  await doAdopt();\n} catch (e) {\n  if (/frame owner|detached/.test(e.message)) {\n    await page.waitForLoadState('load');\n    return doAdopt(); // one retry with a fresh frame\n  }\n  throw e;\n}","preventionTips":["Never reuse execution contexts or handles across page.goto","Wait for load state after navigation before frame/handle operations","Fetch frames fresh from page.frames() each time instead of caching them"],"tags":["browser","execution-context","frame","navigation"],"backgroundTag":"execution-context-destroyed","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}