grafana/k6 · error
focusing on element
Error message
focusing on element: %w
What it means
ElementHandle.focus() wraps the failure of a focus action that evaluates injected.focusNode on the element via CDP with no actionability preconditions. The wrapped error is usually a JavaScript evaluation failure (detached handle or destroyed execution context), a DOM error string returned by the injected script, or a timeout.
Solutions
- Re-acquire the element handle right before focusing it
- Wait for the page/frame to be ready: page.waitForLoadState() before the action
- Verify the element is still attached: await el.evaluate(e => e.isConnected)
- Raise K6_BROWSER_TIMEOUT if the session is just slow
Example fix
// before
const el = await page.$('#search');
await page.goto('https://app.example.com');
await el.focus(); // handle from previous page is dead
// after
await page.goto('https://app.example.com');
const el = await page.$('#search');
await el.focus(); Defensive patterns
Strategy: try-catch
Validate before calling
// Only focus elements confirmed to still be in the DOM
const connected = await el.evaluate((e) => e.isConnected).catch(() => false);
if (!connected) throw new Error('handle is stale; re-query before focus()');
await el.focus(); Try / catch
try {
await el.focus();
} catch (e) {
if (/Could not find object|Execution context|timed out/i.test(String(e.message))) {
const fresh = await page.$(sel); // one re-query retry
await fresh.focus();
} else throw e;
} Prevention
- Re-query elements after page.goto() or waitForNavigation()
- Do not cache handles across async waits that can trigger re-renders
- Raise K6_BROWSER_TIMEOUT for consistently slow environments instead of retrying blindly
When it happens
Trigger: The element handle was detached by navigation or an SPA re-render so Runtime.callFunctionOn fails; the page navigates during the call destroying the execution context; the element sits in a frame that was closed; the default timeout (30s) expires on a stalled session.
Common situations: Focusing fields in SPAs right after route changes; handles stored in variables across page.goto() calls; interacting with elements in popups/iframes that the page closed.
Related errors
- getting element's inner HTML
- getting element's inner text
- dispatching element event
- getting attribute of element
- checking element is checked
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/3392106af78fbebe.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:934
return fmt.Errorf("filling element: %w", err)
}
applySlowMo(h.ctx)
return nil
}
// Focus scrolls element into view and focuses the element.
func (h *ElementHandle) Focus() error {
focus := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return nil, handle.focus(apiCtx, false)
}
opts := NewElementHandleBaseOptions(h.DefaultTimeout())
focusAction := h.newAction(
[]string{}, focus, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
)
if _, err := call(h.ctx, focusAction, opts.Timeout); err != nil {
return fmt.Errorf("focusing on element: %w", err)
}
applySlowMo(h.ctx)
return nil
}
// GetAttribute retrieves the value of specified element attribute.
// The second return value is true if the attribute exists, and false otherwise.
func (h *ElementHandle) GetAttribute(name string) (string, bool, error) {
getAttribute := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return handle.getAttribute(apiCtx, name)
}
opts := NewElementHandleBaseOptions(h.DefaultTimeout())
getAttributeAction := h.newAction(
[]string{}, getAttribute, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,
)
View on GitHub (pinned to 3fcf5388d7)