microsoft / microsoft/aspire

winget uninstall of Microsoft.Aspire leaves ~285 MB after first `aspire` command — bundle extraction into winget package directory breaks clean uninstall

Open
#17,945 2 comments 0 reactions 0 assignees View on GitHub
area-cli triage:bot-seen
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

### Symptom

After installing the Aspire CLI through winget and running any aspire command that touches the bundle (e.g., `aspire doctor`, `aspire run`, `aspire restore`), `winget uninstall Microsoft.Aspire` can no longer cleanly remove the package.

The behavior depends on which flags you pass:

| Command | Exit code | Result |
|---|---|---|
| `winget uninstall --name "Aspire CLI"` | 0 | Succeeds with warning **"Files remain in install directory"**; leaves ~285 MB of bundle/versions content behind |
| `winget uninstall --name "Aspire CLI" --purge` | `0x8a150003` | **Fails** — hash mismatch during purge; package goes into an inconsistent state (winget still lists it; top-level binaries removed; `versions\` directory left behind) |
| `winget uninstall --name "Aspire CLI" --force --purge` | `0x8a150003` | **Fails** — `remove_all: The directory is not empty.: "...\Microsoft.Aspire__DefaultSource"` |

A fresh install with **no** aspire commands run uninstalls cleanly with `--purge`. The breakage only appears after the first command that triggers `WingetFirstRunProbe` + bundle extraction.

### Repro

```powershell
winget install Microsoft.Aspire
aspire doctor # writes sidecar + extracts ~285 MB bundle into pkg dir
winget uninstall --name "Aspire CLI" --purge # fails
```

After the failure, ~285 MB of `versions\-\` content is orphaned under `%LOCALAPPDATA%\Microsoft\WinGet\Packages\Microsoft.Aspire__DefaultSource\`, and the only way out is `Remove-Item -Recurse -Force` plus manual HKCU ARP cleanup.

### Root cause

The CLI is delivered as a winget *portable* install: winget hashes and tracks only the files it places (`aspire.exe`, `Aspire.TypeSystem.xml`, `libsodium.dll`). On first run the CLI then writes new files **into the same directory**:

- `.aspire-install.json` (sidecar from `WingetFirstRunProbe`)
- `.aspire-bundle-version`
- `bundle` symlink
- `versions\-\` (~285 MB extracted bundle)

Winget's portable uninstaller:

- Without `--purge`: refuses to delete untracked files → "Files remain in install directory"
- With `--purge`: tries to wipe the whole directory but verifies hashes of tracked files first; the additions to the directory (and possibly the symlink) trip the integrity check before purge runs, leaving the package half-removed.

This is independent of self-update — it reproduces on any fresh install + any single aspire command. (Self-update would compound it, but the baseline behavior is already broken.)

### Suggested fix

Ship the bundle **pre-extracted in the winget archive** so every file is tracked by winget at install time. Trade-offs:

- ✅ `winget uninstall` (and `--purge`) work cleanly with no leftovers.
- ✅ First aspire command no longer pays the bundle-extraction cost.
- ✅ `winget upgrade` correctly removes old bundle files (today they'd accumulate across versions).
- ⚠️ Winget download grows from ~137 MB → ~422 MB. This is a one-time cost paid at install instead of on first command; the bytes are required either way.

Alternative considered: extract the bundle outside the winget pkg dir (e.g. `%LOCALAPPDATA%\Aspire\bundle\`). Rejected because it defeats #17919's goal of colocating bundle with binary so `winget upgrade` / side-by-side version pinning works.

### Notes

- Reproduced on Windows 11, winget v1.29.170-preview, PR #17919 head `710e1bc`.
- Sidecar-only mutation (without bundle extraction) is enough to trip the "Files remain" warning, but `--purge` only fails once `versions\` is present.
- Refs: PR #17919 (winget bundle colocation), `WingetFirstRunProbe.cs`, `BundleService.ComputeDefaultExtractDir`.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the install and uninstall commands on Windows, then read WingetFirstRunProbe.cs and BundleService.ComputeDefaultExtractDir. Compare the winget archive contents and tracked files with the files created after `aspire doctor`, using PR #17919 as context. Done means a fresh install followed by bundle extraction can be removed cleanly with both normal and `--purge` uninstall.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli, release
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.