grafana/k6 · error
expected node but got %s
Error message
expected node but got %s
What it means
This error is a translation of a raw Chromium DevTools Protocol error whose message starts with 'error:expectednode:'. CDP returns that error when an internal command (DOM.requestNode, DOM.describeNode, DOM.resolveNode) is given a remote object reference that is not a DOM node. k6 rewrites it to 'expected node but got <type>' where <type> is the actual remote object type Chromium reported (e.g. 'object', 'string', 'function'). It almost always means the ElementHandle being used no longer refers to a live DOM node.
Source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1881
case error:
if e == nil {
return errors.New("DOM error is nil")
}
err, serr = e, e.Error()
default:
return fmt.Errorf("unexpected DOM error type %T", v)
}
var uerr *k6ext.UserFriendlyError
if errors.As(err, &uerr) {
return err
}
if strings.Contains(serr, "timed out") {
return &k6ext.UserFriendlyError{
Err: ErrTimedOut,
}
}
if s := "error:expectednode:"; strings.HasPrefix(serr, s) {
return fmt.Errorf("expected node but got %s", strings.TrimPrefix(serr, s))
}
if serr == "error:notconnected" {
return ErrElementNotAttachedToDOM
}
if errors.Is(err, ErrElementNotVisible) {
return ErrElementNotVisible
}
if errors.Is(err, ErrElementNotAttachedToDOM) {
return ErrElementNotAttachedToDOM
}
errs := map[string]string{
"error:notelement": "node is not an element",
"error:nothtmlelement": "not an HTMLElement",
"error:notfillableelement": "element is not an <input>, <textarea> or [contenteditable] element",View on GitHub (pinned to 93accf6570)
Solutions
- Re-acquire the element immediately before acting on it (fresh page.$ / waitForSelector) instead of reusing a cached handle
- Wrap the action in a bounded retry that re-queries the selector when this message appears
- Prefer selector-based auto-waiting APIs (page.click(selector)) over manual handle plumbing
- If it appears intermittently under load, give Chrome more CPU/memory or lower the VU count per browser
Example fix
// before
const btn = await page.$('#submit');
await page.goto('https://example.com/next');
await btn.click(); // stale handle
// after
await page.goto('https://example.com/next');
const btn = await page.$('#submit');
await btn.click(); Defensive patterns
Strategy: retry
Validate before calling
// verify the handle still points at a live, visible node before acting
if (!el) throw new Error('element handle is null');
if (!(await el.isVisible())) throw new Error('element no longer visible'); Type guard
function isElementHandleLike(v) {
return !!v && typeof v.click === 'function' && typeof v.boundingBox === 'function' && typeof v.screenshot === 'function';
} Try / catch
try {
await el.click();
} catch (e) {
if (/expected node but got/.test(e.message)) {
el = await page.waitForSelector(sel, { state: 'visible' }); // re-acquire, retry once
await el.click();
} else throw e;
} Prevention
- Never cache ElementHandles across navigations or SPA route changes
- Prefer selector-based APIs (page.click('#id')) over handle-based ones
- Re-query elements after goto, waitForNavigation, or SPA transitions
- Keep Chrome load reasonable; stale remote objects appear more often on overloaded browsers
When it happens
Trigger: Calling ElementHandle methods that internally resolve or adopt the handle as a node (boundingBox, contentFrame, the cross-context adoption in waitForSelector, clicks on stale handles) after the page navigated or the node was replaced; using a plain JSHandle (a non-element object) where an ElementHandle is required; Chrome disposing remote objects under heavy load.
Common situations: Reusing an ElementHandle obtained before a page.goto or an SPA route change; React/Vue re-rendering a node between query and action; scripts running many VUs against a memory-starved Chrome where remote objects get garbage collected; confusing page.evaluateHandle results (JS values) with element handles.
Related errors
- getting node in frame: %w
- no frame found for node: %w
- resolving DOM node: %w
- describing DOM node: %w
- errorText
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/1890df444785c064.
Report an issue: GitHub.