Skip to content

fix: bypass Selenium Manager only where it cannot run - #188

Merged
juliandescottes merged 2 commits into
mozilla:mainfrom
shoemoney:fix/selenium-manager-browser-resolution
Sep 10, 2026
Merged

juliandescottes merged 2 commits into
mozilla:mainfrom
shoemoney:fix/selenium-manager-browser-resolution

Conversation

@shoemoney

Copy link
Copy Markdown
Contributor

Fixes the browser-resolution regression in 0.10.2 reported by @mightykatun on #170. Their diagnosis was correct and this is essentially the fix they proposed.

What broke

#170 (mine) made every platform pass an explicit geckodriver path to firefox.ServiceBuilder. That fixed aarch64 Linux, where Selenium Manager ships an x86-64 binary that cannot execute, but it regressed everyone else.

selenium-webdriver's Firefox Driver.createSession() calls getBinaryPaths(caps) only when the supplied DriverService has no executable. That one call resolves geckodriver and the Firefox binary, which it then injects into moz:firefoxOptions.binary. Handing the service a path therefore also opts out of finding Firefox.

On a machine with no system Firefox and none on PATH:

  • 0.10.1: Selenium Manager downloads and selects a Firefox under ~/.cache/selenium/firefox/, and list_pages succeeds with no --firefox-path.
  • 0.10.2: first tool call fails with Unable to detect Firefox binary automatically, please provide the full path via --firefox-path.

This is the same mechanism the Android branch in connect() relies on deliberately, where skipping getBinaryPaths() is what stops a desktop binary being injected over androidPackage. The comment there describes the behaviour exactly. I changed the desktop path without noticing it applied there too.

The fix

Bypass Selenium Manager only where it genuinely cannot do the job:

  • win32, where ServiceBuilder() invoked from the MCP hangs (Bug 2040849)
  • non-x64 Linux, where the Selenium Manager binary cannot execute (Bug 2062055)

Everywhere else the executable is left unset, so Selenium Manager resolves both halves as it did in 0.10.1.

On the test

The unit test I added in #170 asserted an explicit service executable on every platform. It encoded the regression as the expected behaviour, so it could never have caught this, and it passed happily while users broke. It is replaced with per-platform cases covering both sides.

I verified these actually fail against the shipped code rather than just passing against mine: reverting core.ts to the 0.10.2 logic fails the two "leaves the service executable unset" cases and passes the rest.

× leaves the service executable unset on linux/x64, so Selenium Manager still finds Firefox
× leaves the service executable unset on darwin/arm64, so Selenium Manager still finds Firefox
  Tests  2 failed | 26 passed (28)

With this change: 686 unit tests pass, lint, prettier and both typecheck configs clean.

Not covered here

The longer-term options @mightykatun raised, an architecture-compatible Selenium Manager binary or our own browser resolver, would let all platforms share one path. This is the minimal restoration of 0.10.1 behaviour for affected users; happy to follow up on either.

Sorry for the breakage, and thanks to @mightykatun for a report that arrived with the root cause already in it.

PR mozilla#170 made every platform pass an explicit geckodriver path to
firefox.ServiceBuilder. That fixed aarch64 Linux, where Selenium Manager ships
an x86-64 binary that cannot execute, but it also regressed browser resolution
in 0.10.2 for everyone else.

selenium-webdriver's Firefox Driver.createSession() calls getBinaryPaths() only
when the supplied DriverService has no executable, and that one call resolves
geckodriver *and* the Firefox binary it injects into moz:firefoxOptions.binary.
Handing the service a path therefore also opts out of finding Firefox. On a
machine with no system Firefox, 0.10.1 launched fine because Selenium Manager
downloaded and selected one under ~/.cache/selenium/firefox/; 0.10.2 fails with
"Unable to detect Firefox binary automatically" unless --firefox-path is given.

This is the same mechanism the Android branch relies on deliberately, where
skipping getBinaryPaths() is what stops a desktop binary being injected over
androidPackage.

Resolve geckodriver ourselves only where Selenium Manager genuinely cannot do
the job: win32, where ServiceBuilder() invoked from the MCP hangs (Bug 2040849),
and non-x64 Linux (Bug 2062055). Elsewhere leave the executable unset so
Selenium Manager resolves both halves as it did in 0.10.1.

The test added in mozilla#170 asserted an explicit path on every platform, so it
encoded the regression as expected behaviour and could not have caught this. It
is replaced with per-platform cases covering both sides, verified to fail
against the 0.10.2 code and pass against this change.

Reported and diagnosed by @mightykatun on mozilla#170.

@juliandescottes juliandescottes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I will just trim the comment and merge.

Comment thread src/firefox/core.ts Outdated
@juliandescottes
juliandescottes merged commit 8183cc7 into mozilla:main Sep 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants