grafana/k6 · error

checking element is enabled

Error message

checking element is enabled: %w

What it means

ElementHandle.isEnabled() runs waitForElementState(['enabled']) with a zero timeout and by design ignores ErrTimedOut. The wrapped error is therefore not 'the element is disabled' (that just returns false) but a hard failure: a detached handle, an execution context destroyed by navigation, or a closed CDP session.

Solutions

  1. Re-query with a live locator: await page.locator(sel).isEnabled()
  2. Re-acquire the element handle immediately before the check
  3. Wrap in try/catch, treating an error as 'element no longer present'
  4. Avoid caching handles across navigations, waits, and multi-step flows

Example fix

// before
const el = await page.$('#submit');
await page.waitForNavigation();
const enabled = await el.isEnabled(); // throws: old page's handle

// after
await page.waitForNavigation();
const enabled = await page.locator('#submit').isEnabled();
Defensive patterns

Strategy: try-catch

Validate before calling

// Check enabled state through a locator that re-resolves the node
const enabled = await page.locator('#submit').isEnabled();

Try / catch

let enabled = false;
try {
  enabled = await el.isEnabled();
} catch (e) {
  if (/not attached|Execution context|Could not find object/i.test(String(e.message))) {
    enabled = await page.locator(sel).isEnabled();
  } else throw e;
}

Prevention

When it happens

Trigger: The button/control node was replaced by an SPA re-render after the handle was taken; the page navigated away; the containing frame was closed; the browser was shutting down when the check ran.

Common situations: Buttons recreated after async state updates (e.g., submit buttons swapped for spinners); cached handles reused after checkout/step transitions; checks racing logout or page close.

Related errors


AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18). Data as JSON: /api/errors/3686667c3d6a2fca. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/common/element_handle.go:1091

}

// 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) {
	ok, err := h.isEnabled(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 enabled: %w", err)
	}

	return ok, nil
}

// IsHidden checks if the element is hidden.
func (h *ElementHandle) IsHidden() (bool, error) {
	ok, err := h.isHidden(h.ctx)
	// We don't care anout timeout errors here!
	if err != nil && !errors.Is(err, ErrTimedOut) {
		return false, fmt.Errorf("checking element is hidden: %w", err)
	}

	return ok, nil
}

// IsVisible checks if the element is visible.
func (h *ElementHandle) IsVisible() (bool, error) {

View on GitHub (pinned to 3fcf5388d7)