{"record":{"id":"a5d107e2af88d02e","repo":"grafana/k6","slug":"getting-attribute-q-of-element-unexpected-type","errorCode":null,"errorMessage":"getting attribute %q of element: unexpected type %T (expecting string)","messagePattern":"getting attribute %q of element: unexpected type %T \\(expecting string\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":962,"sourceCode":"func (h *ElementHandle) GetAttribute(name string) (string, bool, error) {\n\tgetAttribute := func(apiCtx context.Context, handle *ElementHandle) (any, error) {\n\t\treturn handle.getAttribute(apiCtx, name)\n\t}\n\topts := NewElementHandleBaseOptions(h.DefaultTimeout())\n\tgetAttributeAction := h.newAction(\n\t\t[]string{}, getAttribute, opts.Force, withRetry, opts.NoWaitAfter, opts.Timeout,\n\t)\n\n\tv, err := call(h.ctx, getAttributeAction, opts.Timeout)\n\tif err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"getting attribute %q of element: %w\", name, err)\n\t}\n\tif v == nil {\n\t\treturn \"\", false, nil\n\t}\n\ts, ok := v.(string)\n\tif !ok {\n\t\treturn \"\", false, fmt.Errorf(\n\t\t\t\"getting attribute %q of element: unexpected type %T (expecting string)\",\n\t\t\tname, v,\n\t\t)\n\t}\n\n\treturn s, true, nil\n}\n\n// Hover scrolls element into view and hovers over its center point.\nfunc (h *ElementHandle) Hover(opts *ElementHandleHoverOptions) error {\n\thover := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) {\n\t\treturn nil, handle.hover(apiCtx, p)\n\t}\n\thoverAction := h.newPointerAction(hover, &opts.ElementHandleBasePointerOptions)\n\tif _, err := call(h.ctx, hoverAction, opts.Timeout); err != nil {\n\t\treturn fmt.Errorf(\"hovering on element: %w\", err)\n\t}\n","sourceCodeStart":944,"sourceCodeEnd":980,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/element_handle.go#L944-L980","documentation":"After the CDP evaluation for ElementHandle.getAttribute() succeeds, a non-nil result that is not a Go string triggers this invariant error. A missing attribute returns JS null (handled earlier as found=false), so this fires only when the page returns some other type - typically because page scripts monkey-patched Element.prototype.getAttribute, or the evaluation returned undefined for an unusual node.","triggerScenarios":"Anti-bot/instrumentation scripts (bot detection, RUM tools) overriding getAttribute on the page; the handle resolved to a non-element node where getAttribute is undefined; a compromised or exotic DOM returned by the page under test.","commonSituations":"Testing pages protected by bot-detection services that patch DOM APIs; unusual shadow-DOM or namespaced nodes; essentially an internal invariant violation that almost never fires on stock pages.","solutions":["Read the attribute through raw evaluation: await el.evaluate((e, n) => e.getAttribute(n), name)","Check whether the page patches DOM APIs: await el.evaluate(() => Element.prototype.getAttribute.toString())","If the page is stock and the error reproduces, report it as a bug to the k6-browser repository with a minimal repro"],"exampleFix":"// before\nconst v = await el.getAttribute('data-id'); // unexpected type error\n\n// after\nlet v;\ntry {\n  v = await el.getAttribute('data-id');\n} catch (e) {\n  v = await el.evaluate((el2, n) => el2.getAttribute(n), 'data-id');\n}","handlingStrategy":"validation","validationCode":"// Detect DOM API tampering before relying on getAttribute\nconst patched = await el.evaluate(\n  () => Element.prototype.getAttribute.toString().includes('[native code]') === false\n);\nif (patched) {\n  const v = await el.evaluate((e, n) => e.getAttribute(n), name);\n} else {\n  const v = await el.getAttribute(name);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const v = await el.getAttribute(name);\n} catch (e) {\n  if (/unexpected type/i.test(String(e.message))) {\n    const v = await el.evaluate((e2, n) => e2.getAttribute(n), name); // raw read\n  } else throw e;\n}","preventionTips":["Suspect DOM patching when testing bot-protected or heavily instrumented pages","Use el.evaluate() for attribute reads on pages that override DOM prototypes","Report reproducible cases with unmodified pages to the k6-browser maintainers"],"tags":["browser","get-attribute","type-assertion","dom","k6"],"backgroundTag":"type-assertion-failed","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"}