Skip to content

Stage Windows self-updates before replacing uv.exe - #20855

Closed
DebadityaHait wants to merge 2 commits into
astral-sh:mainfrom
DebadityaHait:fix/windows-self-update-interruption
Closed

DebadityaHait wants to merge 2 commits into
astral-sh:mainfrom
DebadityaHait:fix/windows-self-update-interruption

Conversation

@DebadityaHait

Copy link
Copy Markdown

### Summary

Fix Windows self-updates so an interrupted or failed installation does not leave uv unusable.

Instead of renaming the current uv.exe before running the installer, the updater now stages the new release in a temporary directory. The existing executable remains in place until installation completes successfully, after which uv replaces itself using the Windows-safe self-replacement mechanism.

Addresses #12142.

Changes

  • Install the new release into a temporary directory before replacing the running executable.

  • Keep the existing uv.exe in place while the external installer runs.

  • Replace uv.exe from the staged copy only after installation succeeds.

  • Copy companion binaries from the temporary installation into the existing executable directory.

  • Run the temporary installer with:

    • an isolated configuration directory;
    • PATH modification disabled.
  • Preserve the existing install receipt and shell configuration.

  • Configure the updater child process to terminate when the parent task is interrupted.

  • Remove the previous flow that renamed uv.exe to .previous.exe before installation.

The old flow could leave the canonical executable missing when an update was interrupted. With this change, failed or interrupted installations leave the existing uv.exe available.

Testing

Added a Windows regression test that:

  1. Starts a self-update installer.
  2. Interrupts it after installation begins.
  3. Verifies that the original executable is still present.

The regression test failed against the previous implementation and passes with this change.

Validation completed locally:

cargo test -p uv --lib --features self-update -- --nocapture
# 43 passed

cargo fmt --all --check

cargo clippy -p uv --all-targets --all-features --locked -- -D warnings

Not run locally:

  • Full workspace and integration test suite.
  • A self-update using the real release installer.

These are best covered by CI.

#[cfg(not(windows))]
let installer_install_prefix = install_prefix.as_path();
#[cfg(windows)]
let installer_config_path = Some(temporary_config_dir.path());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pointing XDG_CONFIG_HOME at a TempDir means the installer writes uv-receipt.json into a directory that gets deleted on drop, so %LOCALAPPDATA%\uv\uv-receipt.json still holds the pre-update receipt after a windows self-update (version, bins, binary_aliases all stale). copying it back verbatim would be wrong since install_prefix points at the temp dir, but leaving it entirely untouched means a release that adds a new binary never shows up in the receipt. intentional?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I addressed the receipt-staleness concern. After the staged binaries are installed, I now copy the staged receipt back to the original receipt location, replace its temporary install_prefix with the actual install location, and restore modify_path to the user’s existing setting. I also added regression coverage for this behavior, and CI is passing.

@DebadityaHait
DebadityaHait force-pushed the fix/windows-self-update-interruption branch from 77e107d to 8d9324a Compare August 3, 2026 04:41
@astral-sh-bot

astral-sh-bot Bot commented Sep 16, 2026

Copy link
Copy Markdown

We support using AI (i.e., LLMs) while coding. However, AI should not be used to communicate with maintainers.

Please read and follow our AI policy when submitting issues and pull requests.

@astral-sh-bot astral-sh-bot Bot closed this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants