Skip to content

fix(cli): use os.replace to safely rebuild venv when hermes.exe is running (#37881) - #38797

Closed
ashishpatel26 wants to merge 1 commit into
NousResearch:mainfrom
ashishpatel26:fix/windows-venv-os-replace-37881
Closed

fix(cli): use os.replace to safely rebuild venv when hermes.exe is running (#37881)#38797
ashishpatel26 wants to merge 1 commit into
NousResearch:mainfrom
ashishpatel26:fix/windows-venv-os-replace-37881

Conversation

@ashishpatel26

Copy link
Copy Markdown
Contributor

Summary

Replace shutil.rmtree(ignore_errors=True) in rebuild_venv() with an atomic os.replace() move-aside before recreating the venv.

Root cause (fixes #37881)

When hermes.exe / python.exe is running, Windows holds an exclusive lock on venv\Scripts\python.exe. shutil.rmtree(ignore_errors=True) deletes everything it can (site-packages, certifi's cert bundle) but silently fails on the locked interpreter, leaving a half-gutted venv. The following uv venv then refuses to overwrite ("directory already exists") — bricking the install. Every later HTTPS call dies with FileNotFoundError for the missing cert bundle. No automatic recovery: the venv must be rebuilt by hand.

Fix

os.replace(venv_dir, backup) atomically renames the venv directory. On Windows, renaming a directory containing a running exe succeeds (only deletion fails with ERROR_SHARING_VIOLATION). If the rename fails (venv is locked by an open handle on the dir itself), rebuild_venv aborts cleanly without touching the existing venv and tells the user to stop the gateway/desktop. If the rebuild fails, the backup is restored.

Note: this supersedes the --clear-only approach — uv venv --clear still cannot delete a locked python.exe, so it hits the same ERROR_SHARING_VIOLATION as rmtree. The move-aside is what actually prevents the brick.

Test plan

  • test_moves_old_venv_aside_and_creates_new — happy path, backup cleaned up
  • test_aborts_without_deleting_when_venv_in_useos.replace raises OSError → False returned, existing venv intact, uv venv never called
  • test_restores_backup_on_rebuild_failureuv venv exits non-zero → backup restored, False returned
  • test_rebuild_failure_returns_false — no existing venv, uv venv fails → False

🤖 Generated with Claude Code

…rch#37881)

shutil.rmtree(ignore_errors=True) on a running hermes.exe venv deletes
site-packages and certifi but silently fails on the locked python.exe,
leaving a half-gutted venv that uv then refuses to overwrite — bricking
the install with no recovery path.

Fix: move the old venv aside atomically with os.replace before recreating.
os.replace fails fast (without partial deletion) when the venv is in use,
leaving the existing venv intact. If the rebuild fails, the backup is
restored so Hermes never ends up with no venv.
@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles labels Jun 4, 2026
@teknium1

teknium1 commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Thanks for this — the os.replace move-aside idea is a clean way to avoid gutting the venv in place.

The underlying brick is already fixed on main by #38887 ("fix(update): harden venv rebuild + verify core deps after install"), which adds the --clear retry in rebuild_venv() plus a post-install core-deps verification. Closing as redundant with the shipped fix. Thanks for contributing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: hermes update bricks the install on Windows — venv rebuild leaves a venv with no pyvenv.cfg, then ModuleNotFoundError: hermes_cli

3 participants