Skip to content

fix(cli): stop browser --force from deleting chrome under running renders - #4901

Merged
miguel-heygen merged 4 commits into
mainfrom
fix/cli-browser-cache-atomic-install
Oct 2, 2026
Merged

miguel-heygen merged 4 commits into
mainfrom
fix/cli-browser-cache-atomic-install

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

What

hyperframes browser ensure --force, and the corrupt-archive retry, no longer delete the whole managed Chrome cache. A fresh chrome-headless-shell is downloaded into a private staging folder next to the cache and then swapped in by rename, replacing only its own version folder.

Why

Both paths ran rm -rf ~/.cache/hyperframes/chrome (the forced path through clearBrowser()). The install lock only serializes installers, so any render or benchmark already using that binary lost chrome-headless-shell partway through its run.

Repro on main: start a long render, then run hyperframes browser ensure --force in another shell. The render's browser binary disappears while the download runs.

Related work

None. browser clear keeps deleting the whole cache on purpose: you only run it by hand.

How

  • downloadBrowser installs with cacheDir set to ~/.cache/hyperframes/.chrome-staging-<uuid>. That folder sits on the same filesystem as the cache, so the rename is atomic.
  • moveStagedInstallIntoCache moves the existing version folder aside, renames the staged one into place, then deletes the old copy. If the second rename fails, the old folder is moved back. On POSIX, a process already running the old binary keeps its inode.
  • The corrupt-archive retry now clears only the staging folder.
  • purgeStaleInstall is gone. Each install starts from a fresh staging folder, so @puppeteer/browsers never sees a half-extracted target folder. A stale partial extract in the cache gets replaced by the same rename.
  • An install killed by Ctrl-C or SIGTERM skips its finally, so its staging folder (and, if it died between the two renames, the set-aside copy) would stay behind. The next install sweeps every .chrome-staging-* and .chrome-replaced-* folder while it holds the install lock, so none of them can belong to a live installer. browser clear sweeps them too.
  • A failed swap now gets the same HYPERFRAMES_BROWSER_PATH hint as a failed download.
  • --force keeps skipping the cache and system-Chrome shortcuts. It no longer purges other cached versions.

Test plan

  • Unit tests added/updated: new keeps a live reader's binary valid while a concurrent --force re-downloads it runs against the real filesystem. Partway through the second --force install it reads the first install's binary path, then checks that the path holds the new build afterwards and that another version's folder survived. The fs mock gained renameSync, and the install mock now stages under the cacheDir it is given.
  • restores the previous version when the staged install cannot be moved in pins the rollback and the hint; sweeps dirs leaked by a killed install on the next install and on clear pins both sweeps. Each goes red when its line is removed (rollback restore, sweep in the installer, sweep in clearBrowser, swap error outside the hint wrapper): 1 failed, 51 passed each time. 52 passed with everything in place.
  • Red without the fix: with manager.ts reverted to main, the new test fails with ENOENT ... chrome-headless-shell mid-install (2 failed, 48 passed). With the fix: 50 passed, exit 0.
  • Manual testing performed
  • Documentation updated (if applicable)
  • Comments follow CONTRIBUTING.md "Comments": they say why, not what, and a bug fix says what the code must do and how to reproduce the bug

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 1216 (base branch 1216), smooth 1048 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (1)

Unstable (1)

  • seqnudge-none-px-r0-nested-z100: tracking 0.05, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@miguel-heygen
miguel-heygen marked this pull request as ready for review October 2, 2026 15:34
@miguel-heygen
miguel-heygen merged commit f16e509 into main Oct 2, 2026
94 checks passed
@miguel-heygen
miguel-heygen deleted the fix/cli-browser-cache-atomic-install branch October 2, 2026 15:36
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.

1 participant