grafana/k6 · error
does not have a frame owner
Error message
does not have a frame owner
What it means
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.
Source
Thrown at internal/js/modules/k6/browser/common/execution_context.go:141
esid target.SessionID
)
if eh.frame != nil {
efid = cdp.FrameID(eh.frame.ID())
}
if eh.session != nil {
esid = eh.session.ID()
}
e.logger.Debugf(
"ExecutionContext:adoptElementHandle",
"sid:%s stid:%s fid:%s ectxid:%d furl:%q ehtid:%s ehsid:%s",
e.sid, e.stid, e.fid, e.id, e.furl,
efid, esid)
if eh.execCtx == e {
return nil, errors.New("already belongs to the same execution context")
}
if e.frame == nil {
return nil, errors.New("does not have a frame owner")
}
var node *cdp.Node
var err error
action := dom.DescribeNode().WithObjectID(eh.remoteObject.ObjectID)
if node, err = action.Do(cdp.WithExecutor(e.ctx, e.session)); err != nil {
return nil, fmt.Errorf("describing DOM node: %w", err)
}
return e.adoptBackendNodeID(node.BackendNodeID)
}
// eval evaluates the provided JavaScript within this execution context and
// returns a value or handle.
//
//nolint:funlen
func (e *ExecutionContext) eval(View on GitHub (pinned to 01ffac6f24)
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
Defensive patterns
Strategy: retry
Validate before calling
// Stabilize before DOM operations that transfer handles
await page.waitForLoadState('load');
const frame = page.frames().find(f => f.name() === 'app');
if (!frame) throw new Error('frame not (yet) available'); Try / catch
try {
await doAdopt();
} catch (e) {
if (/frame owner|detached/.test(e.message)) {
await page.waitForLoadState('load');
return doAdopt(); // one retry with a fresh frame
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Heavy SPA navigation while holding element handles; iframes removed from the DOM mid-wait; contexts captured before navigation and reused after it completes.
Related errors
- Unexpected end of selector while parsing selector `${selecto
- "${attr}" attribute is only supported for roles: ${roles.sli
- parsing frame navigation options to %q: %w
- getting injected script: %w
- setting content: %w
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/1f2ccedb4d2e1813.
Report an issue: GitHub.