grafana/k6 · error
waiting for selector %q did not result in any nodes
Error message
waiting for selector %q did not result in any nodes
What it means
Frame.waitForSelector runs an internal wait (frame.go:535) that retries up to 20 times on navigation-class errors. If the wait finishes without an error but produced no node handle — handle == nil — k6 reports this error instead of returning null like Playwright. The nil-handle outcome occurs when the wait resolves on a state that legitimately has no node: waiting with state:'hidden'/'detached' semantics where the element is absent or hidden, or the element matched and then disappeared before the handle was returned.
Source
Thrown at internal/js/modules/k6/browser/common/frame.go:499
return nil, err
}
// waitForSelector will wait for the given selector to reach a defined state in
// opts.
//
// It will auto retry on certain errors until the retryCount is below 0. The
// retry workaround is needed since the underlying DOM can change when the
// wait action is performed during a navigation.
func (f *Frame) waitForSelector(selector string, opts *FrameWaitForSelectorOptions) (*ElementHandle, error) {
f.log.Debugf("Frame:waitForSelector", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector)
handle, err := f.waitFor(selector, opts, 20)
if err != nil {
return nil, err
}
if handle == nil {
return nil, fmt.Errorf("waiting for selector %q did not result in any nodes", selector)
}
// We always return ElementHandles in the main execution context (aka "DOM world")
f.executionContextMu.RLock()
defer f.executionContextMu.RUnlock()
uec := f.executionContexts[utilityWorld]
// An element should belong to the current main world execution context, and
// not to the utility world context, otherwise, we should adopt it to the
// current world's execution context. This is only valid when the handle
// is from the current frame and not part of a nested frame.
adopted := handle
if uec != nil && uec == handle.execCtx {
wec := f.executionContexts[mainWorld]
if wec == nil {
return nil, fmt.Errorf("waiting for selector %q: execution context %q not found", selector, mainWorld)
}View on GitHub (pinned to 93accf6570)
Solutions
- For absence checks, use waitForFunction(() => !document.querySelector(sel)) instead of waitForSelector with state:'hidden'
- Double-check the selector string (typos, wrong frame scope)
- If the element is expected to exist, wait with state:'visible' and a timeout that covers rendering
- Retry the wait once if a re-render race is likely
Example fix
// before
await page.waitForSelector('#toast', { state: 'hidden' }); // errors: did not result in any nodes
// after
await page.waitForFunction(() => !document.querySelector('#toast')); Defensive patterns
Strategy: validation
Validate before calling
const el = await page.$('#toast');
if (!el) {
// already absent: no need to wait
} else {
await page.waitForFunction(() => !document.querySelector('#toast'));
} Try / catch
try {
await page.waitForSelector('#x', { state: 'visible' });
} catch (e) {
if (/did not result in any nodes/.test(e.message)) {
// element absent: treat as hidden or re-check the selector
} else throw e;
} Prevention
- Use waitForFunction for absence checks instead of waitForSelector state:'hidden'
- Wait for presence with state:'visible'
- Retry waits around re-render-heavy UIs
When it happens
Trigger: page.waitForSelector(sel, { state: 'hidden' }) where the element is/becomes absent — the wait succeeds with a nil handle and this error fires; an element matched then removed by a re-render before adoption; waiting in a frame whose document keeps changing.
Common situations: Porting Playwright scripts that expect waitForSelector({state:'hidden'}) to resolve null; SPAs aggressively re-rendering matched nodes; selectors that only match text or attributes with no element node.
Related errors
- parsing waitForSelector %q options: %w
- parsing wait for options: %w
- waiting for selector %q: execution context %q not found
- waiting for selector %q: adopting element handle: %w
- waiting for selector %q: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/1296a238ba53b2f1.
Report an issue: GitHub.