JuliusBrussee/caveman · error

select: missing option

Error message

select: missing option

What it means

Returned by the CDPDriver 'select' action when both req.Option and req.Text are empty strings. The driver falls back option := req.Option, then option := req.Text; a select on a <select> element needs a value/label/text to match, so with neither field set the action aborts before touching the page (after scrollIntoView and waitActionable have already passed).

Source

Thrown at browse/cdp.go:205

		if err := chromedp.Run(runCtx, chromedp.ActionFunc(func(actionCtx context.Context) error {
			return input.InsertText(req.Text).Do(actionCtx)
		})); err != nil {
			return ActionResult{OK: false, Settled: false}, err
		}
		return dispatchedAction(), nil
	case "select":
		if err := d.scrollIntoView(runCtx, target); err != nil {
			return ActionResult{OK: false, Settled: false}, err
		}
		if _, _, err := d.waitActionable(runCtx, target); err != nil {
			return ActionResult{OK: false, Settled: false}, err
		}
		option := req.Option
		if option == "" {
			option = req.Text
		}
		if option == "" {
			return ActionResult{OK: false, Settled: false}, errors.New("select: missing option")
		}
		if err := d.callOnNode(runCtx, target, fmt.Sprintf(`function(){ const wanted = %s; const options = Array.from(this.options || []); const match = options.find(o => o.value === wanted || o.label === wanted || o.textContent.trim() === wanted); if (!match) { throw new Error("option not found"); } this.value = match.value; this.dispatchEvent(new Event("input", {bubbles:true})); this.dispatchEvent(new Event("change", {bubbles:true})); return true; }`, jsString(option))); err != nil {
			return ActionResult{OK: false, Settled: false}, err
		}
		return dispatchedAction(), nil
	case "scroll":
		if err := d.scrollIntoView(runCtx, target); err != nil {
			return ActionResult{OK: false, Settled: false}, err
		}
		if _, _, err := d.waitActionable(runCtx, target); err != nil {
			return ActionResult{OK: false, Settled: false}, err
		}
		return dispatchedAction(), nil
	default:
		return ActionResult{OK: false, Settled: false}, fmt.Errorf("unknown action: %s", req.Action)
	}
}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Include the choice: set `option` to the option's value or label, or `text` to its visible text — either is accepted and matched against value, label, and trimmed textContent in order.
  2. Check the exact request field names the driver reads (req.Option, req.Text) if you are building the payload by hand.
  3. Note the target must be an actionable <select> first — but this specific error means the element was fine and only the option string was missing.

Example fix

// before
act(target: "s7", action: "select")  // no option

// after
act(target: "s7", action: "select", option: "US-WEST")
// or: act(target: "s7", action: "select", text: "US West")
Defensive patterns

Strategy: validation

Validate before calling

// Go caller-side check before dispatching to the driver
func validSelect(req ActionRequest) bool {
    return req.Action == "select" && (req.Option != "" || req.Text != "")
}

Prevention

When it happens

Trigger: Calling the browser act tool with action="select" and neither option nor text in the request payload; a client that puts the choice in a differently-named field (e.g. 'value') the driver does not read.

Common situations: Agent formats a select action from a plan and forgets the target option; MCP client schema drift where the field is named differently across versions; selecting the first option by convention without specifying it.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/69d218e87c55f8c6. Report an issue: GitHub.