{"record":{"id":"d095d87f7459c43c","repo":"grafana/k6","slug":"checking-element-is-editable-w","errorCode":null,"errorMessage":"checking element is editable: %w","messagePattern":"checking element is editable: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":1080,"sourceCode":"}\n\n// IsDisabled checks if the element is disabled.\nfunc (h *ElementHandle) IsDisabled() (bool, error) {\n\tok, err := h.isDisabled(h.ctx, 0)\n\t// We don't care anout timeout errors here!\n\tif err != nil && !errors.Is(err, ErrTimedOut) {\n\t\treturn false, fmt.Errorf(\"checking element is disabled: %w\", err)\n\t}\n\n\treturn ok, nil\n}\n\n// IsEditable checks if the element is editable.\nfunc (h *ElementHandle) IsEditable() (bool, error) {\n\tok, err := h.isEditable(h.ctx, 0)\n\t// We don't care anout timeout errors here!\n\tif err != nil && !errors.Is(err, ErrTimedOut) {\n\t\treturn false, fmt.Errorf(\"checking element is editable: %w\", err)\n\t}\n\n\treturn ok, nil\n}\n\n// IsEnabled checks if the element is enabled.\nfunc (h *ElementHandle) IsEnabled() (bool, error) {\n\tok, err := h.isEnabled(h.ctx, 0)\n\t// We don't care anout timeout errors here!\n\tif err != nil && !errors.Is(err, ErrTimedOut) {\n\t\treturn false, fmt.Errorf(\"checking element is enabled: %w\", err)\n\t}\n\n\treturn ok, nil\n}\n\n// IsHidden checks if the element is hidden.\nfunc (h *ElementHandle) IsHidden() (bool, error) {","sourceCodeStart":1062,"sourceCodeEnd":1098,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/element_handle.go#L1062-L1098","documentation":"ElementHandle.isEditable() runs waitForElementState(['editable']) with a zero timeout and intentionally ignores ErrTimedOut. Any wrapped error is a hard failure from the injected state-check script or CDP: usually a detached element handle, a destroyed execution context (navigation), or a closed session.","triggerScenarios":"The input node was swapped out by a re-render before the check; the page navigated and destroyed the context; the element is inside a closed iframe; the browser session ended.","commonSituations":"Checking editability of fields in components that re-mount on validation errors; handles reused after route changes; checks racing page teardown at the end of an iteration.","solutions":["Use a live query: await page.locator(sel).isEditable()","Re-acquire the handle right before the check","Catch the error and treat it as 'not editable / element gone' if that matches your test semantics","Confirm the node still exists: await page.$(sel) returns null once removed"],"exampleFix":"// before\nconst el = await page.$('#email');\nawait stepThatReMountsTheForm();\nconst editable = await el.isEditable(); // throws: re-mounted\n\n// after\nawait stepThatReMountsTheForm();\nconst editable = await page.locator('#email').isEditable();","handlingStrategy":"try-catch","validationCode":"// Confirm existence, then check editability live\nif ((await page.$(sel)) === null) throw new Error('field removed from DOM');\nconst editable = await page.locator(sel).isEditable();","typeGuard":null,"tryCatchPattern":"let editable = false;\ntry {\n  editable = await el.isEditable();\n} catch (e) {\n  if (/not attached|Execution context|Could not find object/i.test(String(e.message))) {\n    editable = await page.locator(sel).isEditable();\n  } else throw e;\n}","preventionTips":["Prefer live locator queries over handles for state checks","Re-query components that re-mount inputs during validation flows"],"tags":["browser","element-state","editable","stale-element","k6"],"backgroundTag":"stale-element-reference","analyzedSha":"3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}