grafana/k6 · error
checking element is disabled
Error message
checking element is disabled: %w
What it means
ElementHandle.isDisabled() runs waitForElementState(['disabled']) with a zero timeout and ignores ErrTimedOut by design. The wrapped error therefore comes from the injected script or CDP layer: a detached element handle, an execution context destroyed by navigation, or a closed session - not from the element simply being enabled.
Solutions
- Re-acquire the element or use page.locator(sel).isDisabled() which re-resolves the node
- Treat thrown errors as 'element gone' via try/catch when the check is advisory
- Verify attachment first: await el.evaluate(e => e.isConnected)
- Do not store handles across page.goto() or long async flows
Example fix
// before
const el = await page.$('#submit');
await flowThatReplacesTheButton();
const disabled = await el.isDisabled(); // throws: node replaced
// after
await flowThatReplacesTheButton();
const disabled = await page.locator('#submit').isDisabled(); Defensive patterns
Strategy: try-catch
Validate before calling
// Re-resolve state with a live query const disabled = (await page.$(sel)) === null ? true // gone implies not interactable in most test semantics : await page.locator(sel).isDisabled();
Try / catch
let disabled = false;
try {
disabled = await el.isDisabled();
} catch (e) {
if (/not attached|Execution context|Could not find object/i.test(String(e.message))) {
disabled = await page.locator(sel).isDisabled();
} else throw e;
} Prevention
- Use locators for state assertions so the node is re-resolved each call
- Never cache handles across multi-step flows that rebuild forms
- Note isDisabled() returns false for a live enabled element; only transport errors throw
When it happens
Trigger: The element node was replaced by a re-render after the handle was acquired; navigation destroyed the execution context; the frame or page containing the element closed; the CDP session stalled.
Common situations: Forms whose controls are recreated during multi-step wizards; SPAs re-rendering disabled/enabled buttons on state changes; handles cached from earlier screens.
Related errors
- checking element is checked
- checking element is editable
- checking element is enabled
- checking element is hidden
- checking element is visible
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/38cf16c8fbc11105.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1069
}
// IsChecked checks if a checkbox or radio is checked.
func (h *ElementHandle) IsChecked() (bool, error) {
ok, err := h.isChecked(h.ctx, 0)
// We don't care about timeout errors here!
if err != nil && !errors.Is(err, ErrTimedOut) {
return false, fmt.Errorf("checking element is checked: %w", err)
}
return ok, nil
}
// IsDisabled checks if the element is disabled.
func (h *ElementHandle) IsDisabled() (bool, error) {
ok, err := h.isDisabled(h.ctx, 0)
// We don't care anout timeout errors here!
if err != nil && !errors.Is(err, ErrTimedOut) {
return false, fmt.Errorf("checking element is disabled: %w", err)
}
return ok, nil
}
// IsEditable checks if the element is editable.
func (h *ElementHandle) IsEditable() (bool, error) {
ok, err := h.isEditable(h.ctx, 0)
// We don't care anout timeout errors here!
if err != nil && !errors.Is(err, ErrTimedOut) {
return false, fmt.Errorf("checking element is editable: %w", err)
}
return ok, nil
}
// IsEnabled checks if the element is enabled.
func (h *ElementHandle) IsEnabled() (bool, error) {View on GitHub (pinned to 3fcf5388d7)