Skip to content

BundleService: MoveDirectory fails with "Access denied" when migrating from legacy layout to versioned layout on Windows #18275

Description

@damianog

Is there an existing issue for this?

I have searched the existing issues

Describe the bug

When running aspire update --yes --non-interactive (or aspire setup --force) in a project directory on Windows, the CLI fails with:

❌ Bundle extraction failed. Run 'aspire setup --force' to retry, or reinstall the Aspire CLI.

The log shows the bundle extracts successfully into a .tmp.* directory, but the subsequent MoveDirectory to promote it to the final versioned path always fails with System.IO.IOException: Access to the path '...' is denied:

[FAIL] [BundleService] Failed to promote
  C:\Users\<user>\.aspire\versions\13.4.5_<hash>.tmp.<guid>
  to
  C:\Users\<user>\.aspire\versions\13.4.5_<hash>.
System.IO.IOException: Access to the path '...tmp...' is denied.
   at System.IO.FileSystem.MoveDirectory(String, String, Boolean)
   at Aspire.Cli.Bundles.BundleService.<ExtractVersionedLayoutAsync>d__22.MoveNext()

The versions/ directory does not exist beforehand, user permissions are correct (full control), and the issue is not related to antivirus.

Steps To Reproduce

  1. Install Aspire CLI (e.g. via aspire update --self --channel stable) on a machine where the bundle was previously extracted in the legacy layout (~/.aspire/managed/ and ~/.aspire/dcp/)
  2. Run aspire update --yes --non-interactive in a project directory
  3. Observe the BundleService attempting to extract the bundle into ~/.aspire/versions/<version>.tmp.<guid> and then failing on MoveDirectory

Expected Behavior

The bundle should be promoted from the .tmp.* directory to ~/.aspire/versions/<version> successfully, or the CLI should fall back to the existing legacy layout.

Actual Behavior

MoveDirectory throws IOException: Access to the path is denied even though the user has full permissions on ~/.aspire/versions/.

Workaround

Manually create the target versioned directory and copy managed/ and dcp/ from the legacy layout:

$target = "C:\Users\<user>\.aspire\versions\<version-hash>"
New-Item -ItemType Directory -Force "$target\managed" | Out-Null
New-Item -ItemType Directory -Force "$target\dcp" | Out-Null
Copy-Item -Recurse -Force "C:\Users\<user>\.aspire\managed\*" "$target\managed\"
Copy-Item -Recurse -Force "C:\Users\<user>\.aspire\dcp\*" "$target\dcp\"

Also, updating .aspire-bundle-version to match the CLI version avoids the repeated re-extraction attempts:

Set-Content "C:\Users\<user>\.aspire\.aspire-bundle-version" "13.4.5+<hash>|<id>|<timestamp>"

Environment

  • OS: Windows 11
  • Aspire CLI version: 13.4.5+73114e86c64aeb9f3f3c7da8e37df1ae4281b27e
  • Shell: PowerShell
  • Layout at time of failure: legacy (managed/ + dcp/ directly under ~/.aspire, no versions/ directory)

Additional Context

The issue appears to be specific to the transition from the legacy layout (where managed/ and dcp/ live directly under ~/.aspire) to the new versioned layout (~/.aspire/versions/<hash>/). The MoveDirectory call fails in this scenario on Windows despite correct permissions. The --non-interactive flag also reveals a secondary bug: without it, aspire update --self fails with Cannot show selection prompt since the current terminal isn't interactive, which means the flag is either undocumented or not consistently honored.

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions