grafana/k6 · warning
optionHandle.dispose: %w
Error message
optionHandle.dispose: %w
What it means
After reading each selected option's value, k6 disposes the option's remote object; a failed Runtime.releaseObject surfaces as 'optionHandle.dispose: <cause>'. This is a resource-cleanup error after the useful work already succeeded — the value was read, but the CDP object could not be released.
Source
Thrown at internal/js/modules/k6/browser/common/frame.go:1744
selectHandle, ok := v.(jsHandle)
if !ok {
return nil, fmt.Errorf("unexpected select element type %T", v)
}
// pack the selected <option> values inside <select> into a slice
optHandles, err := selectHandle.getProperties()
if err != nil {
return nil, fmt.Errorf("getProperties: %w", err)
}
vals := make([]string, 0, len(optHandles))
for _, oh := range optHandles {
val, err := oh.JSONValue()
if err != nil {
return nil, fmt.Errorf("reading value: %w", err)
}
vals = append(vals, val)
if err := oh.dispose(); err != nil {
return nil, fmt.Errorf("optionHandle.dispose: %w", err)
}
}
if err := selectHandle.dispose(); err != nil {
return nil, fmt.Errorf("selectHandle.dispose: %w", err)
}
return vals, nil
}
// SetContent replaces the entire HTML document content.
func (f *Frame) SetContent(html string, _ *FrameSetContentOptions) error {
f.log.Debugf("Frame:SetContent", "fid:%s furl:%q", f.ID(), f.URL())
// TODO(@inancgumus): Respect the FrameSetContentOptions before executing the action.
// A solution is similar to the logic in `WaitForLoadState`.
js := `(html) => {
window.stop();View on GitHub (pinned to 93accf6570)
Solutions
- If occasional, wrap selectOption and verify the selection afterwards via evaluate instead of trusting the return path.
- Avoid closing the page or navigating immediately after selectOption.
- If it fires consistently, update k6 — dispose ordering in the selectOption readback has been improved across releases.
Example fix
// before
const v = await page.selectOption('#sel', 'x');
await page.close(); // races dispose
// after
const v = await page.selectOption('#sel', 'x');
await page.waitForTimeout(50); // let cleanup finish
await page.close(); Defensive patterns
Strategy: try-catch
Try / catch
try { return await page.selectOption(sel, v); }
catch (e) {
if (/optionHandle\.dispose/.test(e.message)) { /* values were read; verify via evaluate */
return page.evaluate(() => [...document.querySelector(sel).selectedOptions].map(o => o.value));
}
throw e;
} Prevention
- Treat dispose failures as post-success cleanup noise; verify state instead
- Avoid navigating or closing the page during selectOption
- Upgrade k6 if dispose errors fire on every selection
When it happens
Trigger: The option's execution context is destroyed between JSONValue() and dispose() (navigation, re-render); the remote object was already garbage-collected or force-released by the browser; the page is closing.
Common situations: Same class as the readback errors: frameworks that rebuild the select on change; page.close() racing the call; mostly harmless unless it fires on every selection, which signals a lifecycle race worth fixing.
Related errors
- getProperties: %w
- selectHandle.dispose: %w
- disposing document element while getting owner frame: %w
- parent frame has been detached
- attaching new page: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/dececde1a990f9d6.
Report an issue: GitHub.