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

  1. Re-acquire the frame and re-query the element after navigation settles (waitForNavigation + fresh page.$)
  2. Wait for a stable state (page.waitForLoadState('load')) before DOM operations that adopt or transfer handles
  3. Drop pre-navigation handles: dispose them and query anew on the current frame
  4. 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

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


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/1f2ccedb4d2e1813. Report an issue: GitHub.