Problem
scripts/firefox_version.py resolves "the latest Firefox release" from the hg tag list: it reads https://hg.mozilla.org/releases/mozilla-release/json-tags, picks the highest FIREFOX_X_Y_Z_RELEASE tag, and pins that tag's node in scripts/install-firefox.sh.
That assumes the revision a release is tagged at is the revision its builds were produced from. That assumption does not always hold, and when it breaks we silently skip a shipped Firefox release.
Evidence (Firefox 153.0.3)
FIREFOX_153_0_3_RELEASE tags node 5ea6f25c57d411c3dea06f0405775b4066302e09. There is no unbranded (add-on-devel) build indexed against that node:
404 gecko.v2.mozilla-release.revision.5ea6f25c...firefox.linux64-add-on-devel
But 153.0.3 unbranded builds do exist. They were built from mozilla-release revision 0cbbe673f58f3b809b3b6313ab0b1495a53af347, which carries no FIREFOX_*_RELEASE tag:
200 gecko.v2.mozilla-release.revision.0cbbe673...firefox.linux64-add-on-devel
200 gecko.v2.mozilla-release.revision.0cbbe673...firefox.macosx64-add-on-devel
and that revision self-identifies as the same release:
$ curl -sL https://hg.mozilla.org/releases/mozilla-release/raw-file/0cbbe673.../browser/config/version.txt
153.0.3
gecko.v2.mozilla-release.latest.firefox.linux64-add-on-devel points at that build (task IgBMUW2YTtGQ6GzEJ2RqRg, created 2026-08-03), confirming it is the newest unbranded release build available — not 153.0.1's.
Separately worth recording, since it looked like the cause at first: the tagged 153.0.3 revision also has a visibly trimmed task graph (162 indexed firefox.* tasks vs 195 for 153.0.1), missing all *-add-on-devel, linux64-debug, linux64-asan-opt/tsan-opt, and every sm-* SpiderMonkey job. So both things are true: that node was built with a reduced graph, and the full build happened at a later untagged revision.
Impact
We pin one release behind the true latest stable whenever this happens. OpenWPM's stated requirement is to track the latest stable Firefox, so this quietly violates it. In #1216-adjacent terms it is a correctness-of-tooling issue, not a crawl-data issue.
Today this is masked rather than silent: firefox_version.py now verifies unbranded builds exist for a tag's revision before pinning it (added alongside the v0.36.0 release prep), and logs Skipping <tag>: no unbranded build on TaskCluster. Before that check, the bad node was pinned happily and only failed with a 404 at install-firefox.sh download time — the failure mode from #964.
Proposed fix
Treat the TaskCluster index, not the hg tag list, as the source of truth for "the latest installable Firefox":
- Resolve
gecko.v2.mozilla-release.latest.firefox.<platform>-add-on-devel for every platform install-firefox.sh supports.
- Read
payload.env.GECKO_HEAD_REV from the resolved task to get the build revision.
- Confirm the platforms agree on that revision, and read
browser/config/version.txt at it to get the human-facing version for the # FIREFOX_..._RELEASE-style comment and for strict_min_version.
- Pin that revision.
This makes the pin "the newest revision that actually has unbranded builds on every supported platform", which is exactly the property install-firefox.sh needs, and it removes the tag-node assumption entirely.
Trade-offs to weigh
- The comment in
install-firefox.sh currently names a tag (# FIREFOX_153_0_1_RELEASE). With index-based resolution the pinned revision may have no tag, so the comment would have to carry a version string plus revision instead. That is a small readability regression in exchange for correctness.
- It trusts TaskCluster index retention. Builds expire (the current ones expire ~1 year out), so a long-untouched checkout could reference an expired task — same exposure as today, since
install-firefox.sh already downloads from that index.
mozilla-central does not expose latest.firefox.*-add-on-devel under the same namespace, so this logic is mozilla-release-specific. That is fine — we only ever track release.
Workaround in the meantime
fetch_latest() walks back up to _MAX_TAG_LOOKBACK tags and picks the newest one whose tagged revision does have unbranded builds, so releases like this degrade to "one version behind" with a printed reason rather than a broken install.
Problem
scripts/firefox_version.pyresolves "the latest Firefox release" from the hg tag list: it readshttps://hg.mozilla.org/releases/mozilla-release/json-tags, picks the highestFIREFOX_X_Y_Z_RELEASEtag, and pins that tag's node inscripts/install-firefox.sh.That assumes the revision a release is tagged at is the revision its builds were produced from. That assumption does not always hold, and when it breaks we silently skip a shipped Firefox release.
Evidence (Firefox 153.0.3)
FIREFOX_153_0_3_RELEASEtags node5ea6f25c57d411c3dea06f0405775b4066302e09. There is no unbranded (add-on-devel) build indexed against that node:But 153.0.3 unbranded builds do exist. They were built from
mozilla-releaserevision0cbbe673f58f3b809b3b6313ab0b1495a53af347, which carries noFIREFOX_*_RELEASEtag:and that revision self-identifies as the same release:
gecko.v2.mozilla-release.latest.firefox.linux64-add-on-develpoints at that build (taskIgBMUW2YTtGQ6GzEJ2RqRg, created 2026-08-03), confirming it is the newest unbranded release build available — not 153.0.1's.Separately worth recording, since it looked like the cause at first: the tagged 153.0.3 revision also has a visibly trimmed task graph (162 indexed
firefox.*tasks vs 195 for 153.0.1), missing all*-add-on-devel,linux64-debug,linux64-asan-opt/tsan-opt, and everysm-*SpiderMonkey job. So both things are true: that node was built with a reduced graph, and the full build happened at a later untagged revision.Impact
We pin one release behind the true latest stable whenever this happens. OpenWPM's stated requirement is to track the latest stable Firefox, so this quietly violates it. In #1216-adjacent terms it is a correctness-of-tooling issue, not a crawl-data issue.
Today this is masked rather than silent:
firefox_version.pynow verifies unbranded builds exist for a tag's revision before pinning it (added alongside the v0.36.0 release prep), and logsSkipping <tag>: no unbranded build on TaskCluster. Before that check, the bad node was pinned happily and only failed with a 404 atinstall-firefox.shdownload time — the failure mode from #964.Proposed fix
Treat the TaskCluster index, not the hg tag list, as the source of truth for "the latest installable Firefox":
gecko.v2.mozilla-release.latest.firefox.<platform>-add-on-develfor every platforminstall-firefox.shsupports.payload.env.GECKO_HEAD_REVfrom the resolved task to get the build revision.browser/config/version.txtat it to get the human-facing version for the# FIREFOX_..._RELEASE-style comment and forstrict_min_version.This makes the pin "the newest revision that actually has unbranded builds on every supported platform", which is exactly the property
install-firefox.shneeds, and it removes the tag-node assumption entirely.Trade-offs to weigh
install-firefox.shcurrently names a tag (# FIREFOX_153_0_1_RELEASE). With index-based resolution the pinned revision may have no tag, so the comment would have to carry a version string plus revision instead. That is a small readability regression in exchange for correctness.install-firefox.shalready downloads from that index.mozilla-centraldoes not exposelatest.firefox.*-add-on-develunder the same namespace, so this logic ismozilla-release-specific. That is fine — we only ever track release.Workaround in the meantime
fetch_latest()walks back up to_MAX_TAG_LOOKBACKtags and picks the newest one whose tagged revision does have unbranded builds, so releases like this degrade to "one version behind" with a printed reason rather than a broken install.