alibaba/page-agent · error · Error

Element is not a select element

Error message

Element is not a select element

What it means

selectOptionElement requires an actual <select> element and throws when the passed element fails isSelectElement. Custom dropdowns built from divs/ul/li are not <select>, so option selection by value/text cannot work on them. The library explicitly rejects them rather than misfiring click sequences.

Source

Thrown at packages/page-controller/src/actions.ts:240

	}

	// Only dispatch shared input event for non-contenteditable (contenteditable has its own)
	if (!isContentEditable) {
		element.dispatchEvent(new Event('input', { bubbles: true }))
	}

	await waitFor(0.1)

	blurLastClickedElement()
}

/**
 * @todo browser-use version is very complex and supports menu tags, need to follow up
 * @private Internal method, subject to change at any time.
 */
export async function selectOptionElement(selectElement: HTMLSelectElement, optionText: string) {
	if (!isSelectElement(selectElement)) {
		throw new Error('Element is not a select element')
	}

	const options = Array.from(selectElement.options)
	const option = options.find((opt) => opt.textContent?.trim() === optionText.trim())

	if (!option) {
		throw new Error(`Option with text "${optionText}" not found in select element`)
	}

	selectElement.value = option.value
	selectElement.dispatchEvent(new Event('change', { bubbles: true }))

	await waitFor(0.1) // Wait to ensure change event processing completes
}

interface ScrollableElement extends Element {
	scrollIntoViewIfNeeded?: (centerIfNeeded?: boolean) => void
}

View on GitHub (pinned to d02db1ee7c)

Solutions

  1. Check the element at that index: if it is not <select>, use clickElement to open the dropdown and click the option item instead
  2. Verify with the simplified HTML that a native <select> exists before calling selectOption
  3. Re-run updateTree() if the DOM may have changed since observation
  4. Wrap selectOption in try-catch and fall back to a click-through sequence for custom dropdowns

Example fix

// before
await controller.selectOption(8, 'United States') // index 8 is a div dropdown

// after (custom dropdown): open and click the option
await controller.clickElement(8) // open dropdown
await controller.updateTree()
await controller.clickElement(21) // click desired option li/div
Defensive patterns

Strategy: type-guard

Validate before calling

const el = await controller.element(i); if (!(el instanceof HTMLSelectElement)) { /* use click-through sequence instead of selectOption */ }

Type guard

function isNativeSelect(el: HTMLElement | null): el is HTMLSelectElement { return el instanceof HTMLSelectElement }

Try / catch

try { await controller.selectOption(i, text) } catch (e) { if (String(e).includes('not a select element')) { await controller.clickElement(i); await controller.updateTree(); await controller.clickElement(optionIndex) } else throw e }

Prevention

When it happens

Trigger: Calling selectOption with an index that points to a custom dropdown container (div[role=combobox], ul, button) instead of a native <select>; passing an HTMLElement you obtained yourself that is not a select; the native select was replaced by a widget at that index after re-render.

Common situations: Modern UI libraries (MUI, Ant Design, custom components) render div-based dropdowns; the agent sees a dropdown in the DOM and assumes selectOption applies; index staleness after re-render swapped the node.

Related errors


AI-assisted analysis of alibaba/page-agent@d02db1ee7c (2026-08-28). Data as JSON: /api/errors/2c865f6565bfcdc9. Report an issue: GitHub.