grafana/k6 · error
disposing document element: %w
Error message
disposing document element: %w
What it means
Cleanup error inside ElementHandle.ownerFrame(): the temporary document-element handle acquired during the call could not be disposed in the deferred cleanup, and the error is joined (errors.Join) with the function's return error. Disposal fails when the remote object was already released - most commonly because a navigation destroyed the execution context between evaluation and dispose - or because the CDP session/page is closing.
Source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1144
opts := evalOptions{
forceCallable: true,
returnByValue: false,
}
res, err := h.evalWithScript(h.ctx, opts, fn)
if err != nil {
return nil, fmt.Errorf("getting document element: %w", err)
}
if res == nil {
return nil, errors.New("getting document element: nil document")
}
documentHandle, ok := res.(*ElementHandle)
if !ok {
return nil, fmt.Errorf("unexpected result type while getting document element: %T", res)
}
defer func() {
if err := documentHandle.Dispose(); err != nil {
err = fmt.Errorf("disposing document element: %w", err)
rerr = errors.Join(err, rerr)
}
}()
if documentHandle.remoteObject.ObjectID == "" {
return nil, err
}
var node *cdp.Node
action := dom.DescribeNode().WithObjectID(documentHandle.remoteObject.ObjectID)
if node, err = action.Do(cdp.WithExecutor(h.ctx, h.session)); err != nil {
return nil, fmt.Errorf("getting node in frame: %w", err)
}
if node == nil || node.FrameID == "" {
return nil, fmt.Errorf("no frame found for node: %w", err)
}
frame, ok := h.frame.manager.getFrameByID(node.FrameID)View on GitHub (pinned to 93accf6570)
Solutions
- Stabilize the page before calling: await page.waitForLoadState('load')
- Re-query the element handle immediately before ownerFrame()
- Treat the failure as transient: retry ownerFrame() once after the page settles
- Upgrade k6 - dispose failures are joined so they surface; newer releases handle context destruction more gracefully
Example fix
// before
const f = await h.ownerFrame();
// after
await page.waitForLoadState('load');
let f;
try {
f = await h.ownerFrame();
} catch (e) {
f = await (await page.$('#in-frame')).ownerFrame(); // retry with a fresh handle
} Defensive patterns
Strategy: try-catch
Validate before calling
await page.waitForLoadState('load');
const el = await page.$('#in-frame');
if (el) {
const frame = await el.ownerFrame();
} Try / catch
try {
frame = await handle.ownerFrame();
} catch (e) {
if (String(e).includes('disposing document element')) {
await page.waitForLoadState('load');
frame = await (await page.$(sel)).ownerFrame(); // retry with fresh handle
} else {
throw e;
}
} Prevention
- Stabilize the page (waitForLoadState) before frame resolution
- Retry ownerFrame once after navigation races - the dispose failure is transient
- Do not call ownerFrame while closing the browser context
- Keep k6 current to benefit from improved context-destruction handling
When it happens
Trigger: The page navigates between the getDocumentElement evaluation and the deferred Dispose; the browser context or page is closed while ownerFrame() runs; the remote object was already garbage-collected/released; the CDP session dropped.
Common situations: ownerFrame() racing a redirect or form submit; iframe content reloading concurrently; browser shutdown at the end of a scenario while frame resolution is in flight.
Related errors
- getting document element: %w
- getting node in frame: %w
- expected node but got %s
- resolving DOM node: %w
- describing DOM node: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/06732cc10e31684e.
Report an issue: GitHub.