{"record":{"id":"97ef4a90c0bbdd42","repo":"grafana/k6","slug":"waiting-for-selector-q-adopting-element-handle","errorCode":null,"errorMessage":"waiting for selector %q: adopting element handle: %w","messagePattern":"waiting for selector %q: adopting element handle: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/frame.go","lineNumber":520,"sourceCode":"\t// We always return ElementHandles in the main execution context (aka \"DOM world\")\n\tf.executionContextMu.RLock()\n\tdefer f.executionContextMu.RUnlock()\n\n\tuec := f.executionContexts[utilityWorld]\n\n\t// An element should belong to the current main world execution context, and\n\t// not to the utility world context, otherwise, we should adopt it to the\n\t// current world's execution context. This is only valid when the handle\n\t// is from the current frame and not part of a nested frame.\n\tadopted := handle\n\tif uec != nil && uec == handle.execCtx {\n\t\twec := f.executionContexts[mainWorld]\n\t\tif wec == nil {\n\t\t\treturn nil, fmt.Errorf(\"waiting for selector %q: execution context %q not found\", selector, mainWorld)\n\t\t}\n\n\t\tif adopted, err = wec.adoptElementHandle(handle); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"waiting for selector %q: adopting element handle: %w\", selector, err)\n\t\t}\n\n\t\tif err = handle.Dispose(); err != nil {\n\t\t\tf.log.Warnf(\n\t\t\t\t\"Frame:waitForSelector\",\n\t\t\t\t\"fid:%s furl:%q sel:%q disposing element handle: %v\",\n\t\t\t\tf.ID(), f.URL(), selector, err,\n\t\t\t)\n\t\t}\n\t}\n\n\treturn adopted, nil\n}\n\nfunc (f *Frame) waitFor(\n\tselector string, opts *FrameWaitForSelectorOptions, retryCount int,\n) (_ *ElementHandle, rerr error) {\n\tf.log.Debugf(\"Frame:waitFor\", \"fid:%s furl:%q sel:%q\", f.ID(), f.URL(), selector)","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/frame.go#L502-L538","documentation":"The final adoption of a found element from the utility world into the main world failed; this wraps the adoptElementHandle error, which itself covers DOM.describeNode/DOM.resolveNode failures (see 746/744). It is the same navigation/disposal race in waitForSelector's adoption path: the handle stopped being adoptable — context destroyed, object disposed, frame detached — between being found and being moved.","triggerScenarios":"waitForSelector racing a navigation (describeNode fails on a disposed object during adoption); the element removed by a re-render mid-adoption; cross-frame handles whose source frame navigated.","commonSituations":"Fast SPA transitions during waits; elements replaced by animations or virtual scrolling; load-induced disposal of remote objects.","solutions":["Retry the wait — the element will be re-found in the new context without adoption","Stabilize timing with waitForLoadState before querying","Prefer one-shot selector-action APIs (page.click(sel)) which handle retries internally"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  el = await page.waitForSelector('#x');\n} catch (e) {\n  if (/adopting element handle/.test(e.message)) {\n    await page.waitForLoadState();\n    el = await page.waitForSelector('#x');\n  } else throw e;\n}","preventionTips":["Prefer one-shot selector-action APIs (page.click(sel)) which retry internally","Stabilize the page before querying on animation/virtual-scroll UIs","Do not store handles across re-render boundaries"],"tags":["browser","execution-context","navigation","race-condition","wait-for-selector"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}