grafana/k6 · error
getting remote node
Error message
getting remote node %q: %w
What it means
ContentFrame() starts with a CDP dom.DescribeNode call for the element's remote object; this error wraps that protocol call failing. The remote object ID became unusable — the element was removed by a navigation/re-render, the execution context was destroyed, or the browser session/target is gone.
Solutions
- Re-query the element immediately before calling contentFrame() — do not cache handles across navigations
- Wait for the page/frame to settle: await page.waitForLoadState('load') before resolving the iframe element
- On failure, retry the whole query-and-step-in sequence once after a short wait
- Verify the session is alive (page.isClosed()) and restart the iteration if the browser crashed
Example fix
// before
const el = await page.$('iframe#app');
await page.reload();
const frame = await el.contentFrame(); // stale
// after
await page.reload();
const el = await page.$('iframe#app');
const frame = await el.contentFrame(); Defensive patterns
Strategy: retry
Validate before calling
if (page.isClosed()) throw new Error('page closed; stale handle unusable');
await page.waitForLoadState('load');
const el = await page.$('iframe#app'); // fresh handle after navigation Try / catch
let frame;
for (let attempt = 0; attempt < 2; attempt++) {
try {
frame = await el.contentFrame();
break;
} catch (e) {
if (attempt === 1 || page.isClosed()) throw e;
await page.waitForTimeout(500);
el = await page.$('iframe#app'); // re-acquire
}
} Prevention
- Re-query iframe elements after every navigation or SPA route change
- Wait for load state before resolving elements you plan to step into
- Treat DescribeNode failures as staleness: refresh the handle, don't retry the stale one
When it happens
Trigger: Calling contentFrame() (or frame-chained selectors that step into iframes) on a handle whose node no longer exists: the page navigated after the handle was created, an SPA re-rendered the iframe away, or the renderer/session died; DescribeNode rejects the stale ObjectID.
Common situations: Holding element handles across page.goto or SPA route changes; iframes recreated by frameworks on each render; remote/cloud browsers dropping sessions; timing races right after load events.
Related errors
- frame not found for id
- creating a new
- Error while parsing selector
- frame has been detached
- getting bounding box of parent frame
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/5d86bf90cd4ca06d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:859
&opts.ElementHandleBasePointerOptions,
)
if _, err := call(h.ctx, click, opts.Timeout); err != nil {
return fmt.Errorf("clicking on element: %w", err)
}
applySlowMo(h.ctx)
return nil
}
// ContentFrame returns the frame that contains this element.
func (h *ElementHandle) ContentFrame() (*Frame, error) {
var (
node *cdp.Node
err error
)
action := dom.DescribeNode().WithObjectID(h.remoteObject.ObjectID)
if node, err = action.Do(cdp.WithExecutor(h.ctx, h.session)); err != nil {
return nil, fmt.Errorf("getting remote node %q: %w", h.remoteObject.ObjectID, err)
}
if node == nil || node.FrameID == "" {
return nil, fmt.Errorf("element is not an iframe")
}
frame, ok := h.frame.manager.getFrameByID(node.FrameID)
if !ok {
return nil, fmt.Errorf("frame not found for id %s", node.FrameID)
}
return frame, nil
}
// Dblclick scrolls element into view and double clicks on the element.
func (h *ElementHandle) Dblclick(opts *ElementHandleDblclickOptions) error {
dblclick := func(_ context.Context, handle *ElementHandle, p *Position) (any, error) {
return nil, handle.dblclick(p, opts.ToMouseClickOptions())
}View on GitHub (pinned to 3fcf5388d7)