{"record":{"id":"e2840528bc764522","repo":"grafana/k6","slug":"frame-has-been-detached-1","errorCode":null,"errorMessage":"frame has been detached 1","messagePattern":"frame has been detached 1","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/page.go","lineNumber":653,"sourceCode":"\t_, err := action.Do(cdp.WithExecutor(p.ctx, p.session))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"evaluating script on document: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (p *Page) getFrameElement(f *Frame) (handle *ElementHandle, _ error) {\n\tif f == nil {\n\t\tp.logger.Debugf(\"Page:getFrameElement\", \"sid:%v frame:nil\", p.sessionID())\n\t} else {\n\t\tp.logger.Debugf(\"Page:getFrameElement\", \"sid:%v fid:%s furl:%s\",\n\t\t\tp.sessionID(), f.ID(), f.URL())\n\t}\n\n\tparent := f.parentFrame\n\tif parent == nil {\n\t\treturn nil, errors.New(\"frame has been detached 1\")\n\t}\n\n\trootFrame := f\n\tfor ; rootFrame.parentFrame != nil; rootFrame = rootFrame.parentFrame {\n\t}\n\n\tparentSession, ok := p.getFrameSession(cdp.FrameID(rootFrame.ID()))\n\tif !ok {\n\t\treturn nil, errors.New(\"parent frame has been detached\")\n\t}\n\n\taction := dom.GetFrameOwner(cdp.FrameID(f.ID()))\n\tbackendNodeID, _, err := action.Do(cdp.WithExecutor(p.ctx, parentSession.session))\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"frame with the given id was not found\") {\n\t\t\treturn nil, errors.New(\"frame has been detached\")\n\t\t}\n\t\treturn nil, fmt.Errorf(\"getting frame owner: %w\", err)","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/page.go#L635-L671","documentation":"Page.getFrameElement (page.go:643-655) backs frame.frameElement(). 'frame has been detached 1' is returned when f.parentFrame == nil: the frame has no parent in this page's frame tree, so it is either the main frame (which has no <iframe> element of its own) or it was detached and pruned from the tree.","triggerScenarios":"Calling frameElement() on the main frame; calling it on a child frame whose <iframe> was removed from the DOM between listing frames and making the call.","commonSituations":"Iterating page.frames() and calling frameElement() after the SPA removed the iframe; passing page.mainFrame() where a child frame was expected; frames captured at setup time and reused later.","solutions":["Only call frameElement() on child frames, never on page.mainFrame()","Re-list page.frames() immediately before use to get a live frame reference","Wait for the iframe selector to be attached before resolving its frame element","Wrap in try-catch and re-discover frames when the page mutates iframes dynamically"],"exampleFix":"// before\nconst frame = page.frames()[0]; // may be the main frame\nconst el = await frame.frameElement(); // error: no parent\n\n// after\nconst frame = page.frames().find(f => f !== page.mainFrame());\nif (frame) { const el = await frame.frameElement(); }","handlingStrategy":"try-catch","validationCode":"// Only ask child frames for their frame element\nif (frame === page.mainFrame()) throw new Error('main frame has no frame element');\nconst alive = page.frames().some(f => f === frame);\nif (alive) { const el = await frame.frameElement(); }","typeGuard":null,"tryCatchPattern":"try {\n  const el = await frame.frameElement();\n} catch (e) {\n  if (String(e.message).includes('detached')) {\n    frame = page.frames().find(f => f.name() === wanted); // re-discover\n    el = await frame.frameElement();\n  } else { throw e; }\n}","preventionTips":["Never call frameElement() on page.mainFrame()","Re-list page.frames() right before use rather than caching frame references","Confirm the iframe is still attached to the DOM before resolving its frame element"],"tags":["browser","frame","iframe","detached"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}