grafana/k6 · warning

selectHandle.dispose: %w

Error message

selectHandle.dispose: %w

What it means

The final step of Frame.selectOption's readback disposes the JSHandle wrapping the array of selected options; failure is wrapped as 'selectHandle.dispose: <cause>'. Like 807, the selection succeeded and values were already collected — only releasing the array handle failed, typically because its context died mid-operation.

Source

Thrown at internal/js/modules/k6/browser/common/frame.go:1748

	// 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();
		document.open();
		document.write(html);
		document.close();
	}`

View on GitHub (pinned to 93accf6570)

Solutions

  1. Treat as retryable: verify the selection with evaluate and move on if the dispose fails after values were read.
  2. Serialize teardown — do not call page.close()/browser.close() from another async branch while actions are in flight.
  3. If persistent, upgrade k6 to pick up selectOption readback fixes.

Example fix

// before
let v;
try { v = await page.selectOption('#sel', 'x'); } catch (e) { throw e; }

// after
let v;
try { v = await page.selectOption('#sel', 'x'); }
catch (e) {
  v = await page.evaluate(() => [...document.querySelector('#sel').selectedOptions].map(o => o.value));
}
Defensive patterns

Strategy: try-catch

Try / catch

try { return await page.selectOption(sel, v); }
catch (e) {
  if (/selectHandle\.dispose/.test(e.message)) {
    return page.evaluate(() => [...document.querySelector(sel).selectedOptions].map(o => o.value));
  }
  throw e;
}

Prevention

When it happens

Trigger: Navigation or context destruction between reading option values and disposing the array handle; CDP session torn down (page close, browser crash) during the final cleanup call.

Common situations: onchange handlers triggering navigation/submit; test teardown closing the browser concurrently with the last selectOption; usually intermittent.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/67cea23683c8baf1. Report an issue: GitHub.