Skip to content

fix(windows): auto-detect Firefox binary for per-user installs - #174

Open
freema wants to merge 1 commit into
mainfrom
fix/windows-firefox-binary-detection
Open

fix(windows): auto-detect Firefox binary for per-user installs#174
freema wants to merge 1 commit into
mainfrom
fix/windows-firefox-binary-detection

Conversation

@freema

@freema freema commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Split out of #169, which @juliandescottes asked me to break into smaller pieces. This is the part that needs a decision rather than just a review.

geckodriver only searches the Program Files directories and HKEY_LOCAL_MACHINE for Firefox, so it cannot see an install made without administrator rights: that one lands in %LOCALAPPDATA%\Mozilla Firefox and registers under HKCU. Launching then fails with "Expected browser binary location, but unable to find binary in default location" even though Firefox is installed and working.

You pointed at https://bugzilla.mozilla.org/show_bug.cgi?id=1921933 and you are right that this belongs in geckodriver. I am happy to take that mentored bug. The open question is whether you want an interim workaround in the MCP in the meantime, or would rather wait for the upstream fix and close this. I have referenced the bug in the module header either way, so it is clear this is meant to go away.

Changes from the review on #169:

  • shortened the not-found message to your wording and moved the constant into core.ts, its only caller
  • renamed binaryLookupFailed to windowsBinaryLookupFailed
  • the module and its test now use path.win32 instead of the ambient path. That was the failing check on test(windows): run the integration suite on Windows #169: the suite mocks process.platform but ran on a Linux runner, so PATH was split on : instead of ; and the lookup returned null.

Verified on Windows 11, Node 22.22.0, against a real per-user Firefox 154.0: nothing in either Program Files directory, nothing under HKLM, only %LOCALAPPDATA%\Mozilla Firefox and the HKCU registration. On main that machine fails with the "unable to find binary in default location" message above. On this branch:

  • Firefox launches in 1.1 s and get_firefox_info reports Binary: C:\Users\...\AppData\Local\Mozilla Firefox\firefox.exe (auto-detected)
  • the full server over stdio works end to end: 32 tools listed, navigate_page and evaluate_script both fine
  • lookup order holds: with a Program Files install present it wins over the per-user one, matching geckodriver
  • the fallbacks work in order, PATH then HKCU, and the registry lookup still resolves with an empty PATH, which is what invoking reg.exe by absolute path is for
  • with nothing findable, the error names --firefox-path and keeps the original geckodriver message
  • an explicit --firefox-path skips detection entirely

One gap worth knowing about: a PATH entry wrapped in quotes ("C:\some dir";...) is not unquoted before probing, so that entry is skipped. It falls through to the registry rather than failing, and I left it alone since this module is meant to be short-lived, but say the word and I will strip them.

geckodriver only searches the Program Files directories and
HKEY_LOCAL_MACHINE for Firefox, so it cannot see an install made without
administrator rights: that one lands in %LOCALAPPDATA%\Mozilla Firefox and
registers under HKCU. Launching then fails with "Expected browser binary
location, but unable to find binary in default location" even though
Firefox is installed and working.

Resolve the binary ourselves and pass it as moz:firefoxOptions.binary.
Candidates are probed in geckodriver's own order (Program Files before the
per-user location) so machines where it already works keep resolving to the
same binary, then PATH, then the App Paths registry key. reg.exe is resolved
under %SystemRoot%\System32 rather than through PATH, because an MCP client
can launch the server with a minimal environment and the registry lookup is
the last resort.

When nothing is found, replace geckodriver's message with one that names
--firefox-path. get_firefox_info now reports the detected path so the
resolution is visible when debugging.

This is a workaround for
https://bugzilla.mozilla.org/show_bug.cgi?id=1921933 and can be dropped once
geckodriver does the lookup itself.
@freema
freema requested a review from juliandescottes August 25, 2026 18:10
@freema
freema marked this pull request as ready for review August 25, 2026 20:26
@juliandescottes

Copy link
Copy Markdown
Collaborator

Will finish the review tomorrow, but thanks a lot for splitting the PRs, it is much easier to review for me now!

You pointed at https://bugzilla.mozilla.org/show_bug.cgi?id=1921933 and you are right that this belongs in geckodriver. I am happy to take that mentored bug. The open question is whether you want an interim workaround in the MCP in the meantime, or would rather wait for the upstream fix and close this. I have referenced the bug in the module header either way, so it is clear this is meant to go away.

It's fine to have a workaround temporarily here. Thanks for considering the upstream bug :)

@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 @freema , approach looks good, I think the new error message could also be helpful on other platforms. See suggestions in comments.

Comment thread src/firefox/core.ts
}
if (this.options.firefoxPath) {
firefoxOptions.setBinary(this.options.firefoxPath);
} else {

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.

Let's make that branch windows-only

Suggested change
} else {
} else if (process.platform === 'win32') {

And since binary.ts is a workaround while waiting for a geckodriver fix, let's also update it to clearly be only about windows. windows-binary.ts, and only expose findFirefoxBinaryWindows

Comment thread src/firefox/core.ts
error instanceof Error ? error.message : String(error)
}`
);
}

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.

Even with this flag, we can't be sure the error is related to the missing binary.
geckodriver will look into locations that binary.ts doesn't check.

We can imagine:

  • binary.ts fails to find anything, windowsBinaryLookupFailed = true
  • then geckodriver finds a binary
  • new Builder()... fails for any other reason

-> We would still print an error message suggestion to use --firefox-path, which might be unhelpful.

I would check if the geckodriver error message contains moz:firefoxOptions.binary (that's the capability name for the binary path, only used in that error message and very unlikely to change)

if (message.includes('moz:firefoxOptions.binary')) {

and I would drop windowsBinaryLookupFailed entirely. The missing-binary case isn't Windows-specific: on Linux geckodriver only searches PATH, so an install under /opt hits the same error. No reason to restrict the message to windows only.

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