grafana/k6 · error
resolving DOM node: %w
Error message
resolving DOM node: %w
What it means
ExecutionContext.adoptBackendNodeID wraps a failed CDP DOM.resolveNode call. k6 resolves a backend node ID into a remote object inside a specific execution context (used when adopting element handles across contexts/frames, e.g. inside waitForSelector). The CDP command fails when the backend node ID is stale (page navigated, node removed), when the execution context ID no longer exists, or when the target session is closing.
Source
Thrown at internal/js/modules/k6/browser/common/execution_context.go:105
// Adopts specified backend node into this execution context from another execution context.
func (e *ExecutionContext) adoptBackendNodeID(backendNodeID cdp.BackendNodeID) (*ElementHandle, error) {
e.logger.Debugf(
"ExecutionContext:adoptBackendNodeID",
"sid:%s stid:%s fid:%s ectxid:%d furl:%q bnid:%d",
e.sid, e.stid, e.fid, e.id, e.furl, backendNodeID)
var (
remoteObj *runtime.RemoteObject
err error
)
action := dom.ResolveNode().
WithBackendNodeID(backendNodeID).
WithExecutionContextID(e.id)
if remoteObj, err = action.Do(cdp.WithExecutor(e.ctx, e.session)); err != nil {
return nil, fmt.Errorf("resolving DOM node: %w", err)
}
// This can occur due to race conditions between trying to click on an element
// and chrome moving on (e.g. navigating).
if remoteObj == nil {
return nil, fmt.Errorf(`the page may have navigated away or the element is
now missing. It might happen when k6 and/or Chrome are overloaded. You
might need to increase the compute resources`)
}
return NewJSHandle(e.ctx, e.session, e, e.frame, remoteObj, e.logger).AsElement(), nil
}
// Adopts the specified element handle into this execution context from another execution context.
func (e *ExecutionContext) adoptElementHandle(eh *ElementHandle) (*ElementHandle, error) {
var (
efid cdp.FrameID
esid target.SessionIDView on GitHub (pinned to 93accf6570)
Solutions
- Retry the user-level action: re-query the element and act again — the race is usually transient
- Await navigations with page.waitForNavigation before touching elements
- Give actions an explicit timeout budget so k6's internal retries can absorb the race
- If it repeats, reduce parallelism or load on the Chrome instance
Example fix
// before
await page.click('#go');
await frameEl.click(); // races the navigation triggered by #go
// after
await Promise.all([page.waitForNavigation(), page.click('#go')]);
await frameEl.click(); Defensive patterns
Strategy: retry
Try / catch
async function withRetry(fn, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try { return await fn(); }
catch (e) {
if (!/resolving DOM node|navigated away|Execution context/.test(e.message) || i === attempts - 1) throw e;
}
}
}
await withRetry(() => page.click('#go')); Prevention
- Synchronize with navigations (waitForNavigation) before interacting
- Re-query elements inside the retry, not once outside it
- Keep handle lifetimes short across awaits that can navigate
- Give browser actions explicit timeouts so internal retries have room
When it happens
Trigger: Adopting an element handle right as the page navigates; the frame containing the element being detached; the execution context destroyed between finding the element and resolving it; Chrome target crash or browser shutdown mid-action.
Common situations: SPAs re-rendering or route-changing during element interaction; elements inside iframes that get removed; races between page.goto and element queries; long scripts where the page closes before the last action completes.
Related errors
- getting node in frame: %w
- describing 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/38577938b60d8a2c.
Report an issue: GitHub.