skip to content

Why does Cypress 16 refuse to launch Firefox 128 in a pinned CI image?

level: seniorimportance: should knowfreq 33%

answer

  1. The failure happens before any spec runs
  2. Firefox is automated one way only now
  3. Older builds implement that protocol partially
  4. The floor rose during the Cypress 15 line
  5. Version 140 is the current minimum

basics

~20 s

Cypress automates Firefox through WebDriver BiDi, and Firefox builds below 140 implement it incompletely. Cypress 16 marks such a build unsupported and refuses to launch it, naming the version to install. The fix is to update the pinned image or ESR build.

solid answer

~40 s

As of Cypress 16 the minimum is **Firefox 140**. Cypress drives Firefox exclusively through WebDriver BiDi - the older Chrome DevTools Protocol path for Firefox was dropped in Cypress 15 - and releases below 140 implement BiDi incompletely, so Cypress validates the detected version and refuses rather than failing halfway through a spec. The message is explicit: Cypress does not support running Firefox version 128 due to an incomplete WebDriver BiDi implementation, and to use Firefox with Cypress, install version 140 or newer. The floor moved during the 15 line: Cypress 15.0.0 through 15.18.1 required 135, and 15.19.0 raised it to 140, the oldest line Mozilla still ships. Chrome, Edge, Electron and experimental WebKit are unaffected, and no spec code has to change.

go deeper

for a junior

Know that Cypress supports only recent Firefox versions and that a very old Firefox will not start at all. You are not expected to recall the exact number.

for a middle

Explain that Firefox is automated over WebDriver BiDi only, that incomplete BiDi support sets a hard minimum version, and where Cypress reports that before any test runs.

for a senior

Show the triage: read the launch error above the spec list, print the version the job actually has, locate the pin, and confirm other browsers are green on the same commit.

for a principal

Set the policy for how browser binaries are pinned and bumped across repos so a runner upgrade never collides with a browser that has silently fallen out of the supported window.

This failure looks like a broken pipeline and is actually a supported-version boundary. It shows up the day a team upgrades Cypress while their Firefox binary stays pinned - a Docker tag, an ESR build, or a browser their CI provider installs. ## What actually blocks the launch Cypress automates Firefox through **WebDriver BiDi**. Firefox releases below **140** implement BiDi incompletely, so Cypress validates the detected major version *before* launching and marks the browser unsupported. The message names the offending version and the one to install: > Cypress does not support running Firefox version 128 due to an incomplete WebDriver BiDi implementation. To use Firefox with Cypress, install version 140 or newer. Two details matter when you are reading a CI log at speed: - **It happens before any spec runs.** There is no failing assertion, no screenshot, no video. If your triage starts at the test report you will find nothing. - **It is a property of the browser, not the project.** Nothing in `cypress.config.js`, no flag, and no `--browser` variant re-enables an older Firefox. There is no fallback path to switch to any more. ## The floor moved, and when | Cypress line | Firefox requirement | | --- | --- | | 14.1.0 - 14.x | Automated Firefox 135+ over BiDi, fell back to CDP for older builds | | 15.0.0 - 15.18.1 | Firefox 135 or newer; the CDP fallback was removed | | 15.19.0 - 16.0.0 | Firefox 140 or newer, the oldest line Mozilla still ships | So a suite that upgraded cleanly from Cypress 14 to 15.0 on Firefox 135 can still break later inside the 15 line, or on the jump to 16, without anyone having touched Firefox. That is the trap: the browser did not change, the requirement did. ## Diagnosing it in CI 1. **Read the very top of the run output**, before the spec list. The launch error is there and nowhere else. 2. **Print the version the job actually has** - `firefox --version` in the job, or `npx cypress info`, which reports the browsers Cypress detected and their versions. 3. **Find where the version is pinned.** A `cypress/browsers` or provider image tag, an apt or ESR package, a cached download. Fix it at the pin, not by pinning Cypress back. 4. **Confirm the other browsers still run.** If `--browser chrome` is green on the same commit, you have confirmed a Firefox-specific version boundary rather than an application regression. ## What is not affected - **Chrome, Edge, Electron and experimental WebKit** are untouched by the Firefox floor; they are automated differently. - **Your spec code** does not change. Cypress commands behave the same in Firefox under BiDi - this is about how Cypress talks to the browser, not about the test API. - **Firefox channels are all in scope.** Developer Edition and Nightly are validated the same way as stable; they are simply always well above the floor. ## Keeping a pinned Firefox launchable - **Treat the Firefox pin as a dependency with an upgrade cadence.** Cypress officially supports the latest three majors of Chrome, Firefox and Edge, so a build pinned and forgotten drifts out of support even when it is above the hard floor. - **Prefer ESR only if you check the line.** An ESR build is attractive because it is stable, and it is exactly the kind of pin that sits below a rising floor. - **Watch the driver, too.** Cypress needs Mozilla's geckodriver to launch Firefox and pulls it through the `geckodriver` npm wrapper package, which downloads a driver when none is cached locally. In an air-gapped environment that download fails and Firefox will not start for an entirely different reason. The `cypress/browsers` and `cypress/included` images built with Firefox 139 or newer ship a geckodriver already, and `cypress/factory` 5.9.0 or newer can build a custom image that includes one. - **Upgrade the browser before the runner.** Bumping Firefox in the image is a small, revertible change; discovering the floor mid-upgrade mixes two problems together and makes the revert ambiguous. - **Read the migration notes for the browser, not only for the API.** A Cypress major's breaking-change list is mostly about commands and configuration, and the browser requirements sit in the same document but are easy to skim past because they change nothing in your code. For a suite covering a bank statement app, the operational rule is simple: whichever Firefox your CI image carries is part of the contract with Cypress, and a Cypress major is the moment to re-read that contract.

  • Which Cypress Docker images already carry a Mozilla geckodriver?
    Cypress needs Mozilla's geckodriver to launch Firefox and pulls it through the `geckodriver` npm wrapper, which downloads one when none is cached - a step that fails in an air-gapped environment. The `cypress/browsers` and `cypress/included` images built with Firefox 139 or newer include a geckodriver already, and `cypress/factory` 5.9.0 or newer can build a custom image that ships one.
  • Does moving Firefox to WebDriver BiDi require any Cypress test changes?
    No. Cypress commands behave identically in Firefox under WebDriver BiDi; what changed is how Cypress talks to the browser, not the spec API. What must change is the binary: any pinned image, ESR build or CI-provider Firefox below version 140 has to be updated before the Cypress upgrade lands, or the browser will not launch at all.

saying these in an interview costs you the question

  • Blames the app or the spec for a launch-time failure
  • Thinks a config flag restores support for older Firefox
  • Assumes Firefox ESR is always a supported Cypress target
  • Believes the version floor applies to Chrome and Edge too
  • Says Cypress still falls back to CDP for old Firefox