Skip to content

fix(extension): reject selectOption when no option matches - #3317

Open
hsusul wants to merge 1 commit into
browserbase:mainfrom
hsusul:fix/select-option-no-match
Open

hsusul wants to merge 1 commit into
browserbase:mainfrom
hsusul:fix/select-option-no-match

Conversation

@hsusul

@hsusul hsusul commented Oct 24, 2026 •

Copy link
Copy Markdown

why

When none of the requested values match an option, locator.selectOption() deselects every option. A single <select> then falls back to its first option, and a multi-select is cleared. input and change still fire, and the call resolves with that first option's value as if it had been chosen:

// <select id="size"><option value="s">Small</option><option value="m" selected>Medium</option></select>
await page.locator("#size").selectOption("Extra Large"); // resolves ["s"], select now shows "Small"

The same path backs act()'s selectOptionFromDropdown. A model value that is slightly off (a typo, or a label that doesn't match exactly) silently submits the wrong choice, and act() reports success. #2953 works around this with a snapshot read-back ("selectOption reports success even when nothing matched"). The Playwright migration guide lists selectOption() as "Same names", and Playwright throws in this case.

what changed

  • selectElementOptions returns null without touching the selection when values were requested but no option matches them. selectOption([]) still clears a multi-select.
  • Locator.selectOption throws Failed to select option (no option matches [...]) for selector: ... on that null. act() already logs and rethrows selection errors.
  • Added an integration test covering a single select and a multi-select: the call rejects, the selection is unchanged, and no change event fires.
  • Patch changeset for the extension and both SDKs.

test plan

  • pnpm exec vitest run -c vitest.integration.config.ts packages/sdk-ts/tests/integration/locatorSelectOption.test.ts: the new test fails before the fix (promise resolved "[ 's' ]" instead of rejecting). After the fix, 11/11 pass.
  • just check passes.
  • pnpm --filter ./packages/extension test:unit: 1054 passed. pnpm --filter ./packages/sdk-ts test:unit: 579 passed.
  • pnpm --filter ./packages/sdk-ts test:browser: 25 passed, 18 skipped. Only rpcClientExtensionSmoke fails, and it fails on main too (path contains a space).
  • Python SDK pytest: 1052 passed, 5 skipped.

Summary by cubic

Rejects locator.selectOption() when no option matches the requested values, instead of silently resetting the <select> to its first option (or clearing a multi-select) and reporting success.

Previously, a single <select> fell back to its first option and the call resolved as if that option was chosen, so a typo or slightly-off label could submit the wrong choice. Now the call throws, the current selection is left unchanged, and no input or change events fire. This aligns the behavior with Playwright, which throws in this case.

Bug Fixes

  • selectElementOptions returns null without touching the selection when values were requested but none match; selectOption([]) still clears a multi-select.
  • Locator.selectOption throws Failed to select option (no option matches [...]).
  • Added integration tests covering single and multi-selects: the call rejects, the selection is unchanged, and no change event fires.
  • Patch changeset for the extension and both SDKs.

Written for commit 4bd81ee. Summary will update on new commits.

View guided diff

selectElementOptions deselected every option when none matched the
requested values, so a single <select> fell back to its first option
(and a multi-select was cleared), input/change fired, and the call
reported that option as selected. Leave the selection untouched and
reject instead.
@changeset-bot

changeset-bot Bot commented Oct 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4bd81ee

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@browserbasehq/stagehand-extension Patch
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-python Patch
browse Patch
@browserbasehq/stagehand-examples Patch
@browserbasehq/stagehand-integrations-claude-cua-sdk Patch
@browserbasehq/stagehand-integrations Patch
@browserbasehq/eve Patch
@browserbasehq/stagehand-integrations-gemini-cua-sdk Patch
@browserbasehq/stagehand-integrations-example-pi-facade Patch
@browserbasehq/stagehand-integrations-claude-agent-sdk Patch
@browserbasehq/stagehand-integrations-example-claude-code-facade Patch
@browserbasehq/stagehand-integrations-codex-sdk Patch
@browserbasehq/stagehand-integrations-example-codex-facade Patch
@browserbasehq/stagehand-integrations-cursor-sdk Patch
@browserbasehq/stagehand-integrations-example-cursor-facade Patch
@browserbasehq/stagehand-integrations-deepagents-sdk Patch
@browserbasehq/stagehand-integrations-eve-sdk Patch
@browserbasehq/stagehand-integrations-fx-sdk Patch
@browserbasehq/stagehand-integrations-mastra-sdk Patch
@browserbasehq/stagehand-integrations-example-mastra-facade Patch
@browserbasehq/stagehand-integrations-pi-sdk Patch
@browserbasehq/stagehand-integrations-example-vercel-ai-facade Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run.
Approving the latest commit mirrors it into an internal PR owned by the approver.
If new commits are pushed later, the internal PR stays open but is marked stale until someone approves the latest external commit and refreshes it.

@github-actions github-actions Bot added external-contributor Tracks PRs mirrored from external contributor forks. external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. labels Oct 24, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. external-contributor Tracks PRs mirrored from external contributor forks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant