grafana/k6 · error
describing DOM node: %w
Error message
describing DOM node: %w
What it means
During adoptElementHandle, k6 calls DOM.describeNode with the source handle's objectID to learn its backend node ID before adopting it into another execution context. The CDP call fails when the remote object behind the handle was already disposed — its objectID is invalid because the owning context was destroyed (navigation), the object was garbage collected, or the session closed.
Source
Thrown at internal/js/modules/k6/browser/common/execution_context.go:149
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(
apiCtx context.Context, opts evalOptions, js string, args ...any,
) (any, error) {
if escapesSobekValues(args...) {
return nil, errors.New("sobek.Value escaped")
}
e.logger.Debugf(
"ExecutionContext:eval",
"sid:%s stid:%s fid:%s ectxid:%d furl:%q %s",View on GitHub (pinned to 93accf6570)
Solutions
- Retry at the user level: re-run the query+action pair — adoption races are transient
- Wait for the page/frame to be idle (waitForLoadState) before querying elements
- Shorten handle lifetime: query, act, discard
- If persistent, check for repeated navigations (redirect loops) on the page
Defensive patterns
Strategy: retry
Try / catch
try {
el = await page.waitForSelector('#x');
} catch (e) {
if (/describing DOM node|adopting element handle/.test(e.message)) {
await page.waitForLoadState();
el = await page.waitForSelector('#x');
} else throw e;
} Prevention
- Do not cache handles across navigation boundaries
- Let auto-waiting APIs do query+action in one step
- Stabilize the page (waitForLoadState) before querying
- Watch for redirect chains that destroy contexts repeatedly
When it happens
Trigger: waitForSelector finds an element in the utility world and adopts it into the main world while a navigation destroys contexts; cross-frame handle adoption after the source frame navigated; holding a handle long enough that Chrome garbage collects the object.
Common situations: Element queries racing page transitions in SPAs; frames/elements replaced between query and adoption inside k6's own waitForSelector path; long-running iterations keeping handles alive past navigations.
Related errors
- getting node in frame: %w
- resolving DOM node: %w
- expected node but got %s
- the page may have navigated away or the element is now mi
- getProperties: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/7ecbd806a5c88616.
Report an issue: GitHub.