microsoft/aspire · error · FileNotFoundException

Extracted CLI executable not found

Error message

Extracted CLI executable not found: {newExePath}

What it means

After downloading and extracting the update archive to a temp directory, the self-update verifies that the expected `aspire` (or `aspire.exe`) executable exists at the expected location inside the extracted payload. If the file is missing, the archive contents differ from expectations and a FileNotFoundException is thrown naming the expected path.

Solutions

  1. Retry `aspire update --self` to re-download a fresh archive
  2. Clear any package/download cache used by the CLI and retry
  3. Verify you are on a supported OS/architecture and that the selected channel publishes archives for it
  4. Fall back to the platform installer script to update instead of the in-place self-update
Defensive patterns

Strategy: retry

Validate before calling

if (!await IsArchiveReachableAsync(archiveUrl))
    Console.Error.WriteLine("Update archive unreachable; check network/channel before self-update.");

Try / catch

try { await UpdateSelfAsync(); }
catch (FileNotFoundException ex) when (ex.Message.Contains("Extracted CLI executable not found"))
{ Console.Error.WriteLine("Archive was incomplete or for the wrong platform; retry or use the installer."); }

Prevention

When it happens

Trigger: `aspire update --self` where the downloaded archive does not contain the platform executable at its root — e.g. a corrupted/truncated download, a channel serving an archive layout for a different platform/OS, or a mismatch between the detected OS and the archive fetched.

Common situations: Proxy or mirror serving a stale/partial archive, architecture mismatch (e.g. arm64 CLI fetching an x64 archive), or interrupted downloads cached by an HTTP layer.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/32584d0438f999dd. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Commands/UpdateCommand.cs:786

        try
        {
            // Extract archive
            await InteractionService.ShowStatusAsync(
                UpdateCommandStrings.ExtractingNewCli,
                async () =>
                {
                    await ArchiveHelper.ExtractAsync(archivePath, tempExtractDir, _environment, cancellationToken);
                    return 0;
                },
                KnownEmojis.Package);

            InteractionService.DisplayMessage(KnownEmojis.Package, UpdateCommandStrings.ExtractedNewCli);

            // Find the aspire executable in the extracted files
            var newExePath = Path.Combine(tempExtractDir, exeName);
            if (!File.Exists(newExePath))
            {
                throw new FileNotFoundException($"Extracted CLI executable not found: {newExePath}");
            }

            // Prepare the sidecar before replacing the running single-file executable. JSON
            // serialization can load framework assemblies lazily, and after replacement the
            // bundle loader could resolve those assemblies from the new executable instead of
            // the bundle used by this process.
            using var sidecarUpdate = InstallSidecarWriter.PrepareForSelfUpdate(installDir, channel);

            // Backup current executable if it exists
            var exeDir = Path.GetDirectoryName(targetExePath)!;
            FileDeleteHelper.TryCleanupOldItems(exeDir, exeName);

            string? backupPath = null;
            if (File.Exists(targetExePath))
            {
                InteractionService.DisplayMessage(KnownEmojis.FloppyDisk, "Backing up current CLI...");

                // Rename current executable to .old.[timestamp]

View on GitHub (pinned to 25830f84bd)