microsoft/aspire · error · InvalidOperationException

The CLI bundle layout was found, but the dashboard binary…

Error message

The CLI bundle layout was found, but the dashboard binary (aspire-managed) is missing. The bundle may be corrupted or incomplete. Run 'aspire setup --force' to re-extract the bundle, or reinstall the Aspire CLI.

What it means

Before profiling, ProfileCaptureService.StartAsync locates the aspire-managed (dashboard) binary from the CLI bundle layout, an ASPIRE_REPO_ROOT repo-local override, or the managed-path environment override. This error is thrown when none of those resolve to an existing file. The CLI considers the bundle corrupted or incomplete and refuses to continue so profiling does not silently bind to the wrong binary.

Solutions

  1. Run 'aspire setup --force' to re-extract a complete CLI bundle.
  2. Reinstall the Aspire CLI if re-extraction does not restore aspire-managed.
  3. Unset or correct the managed-path / ASPIRE_REPO_ROOT environment overrides so they point to a real binary (or remove them to use the default bundle).
  4. If using a repo-local setup, build the dashboard binary in that repo before profiling.

Example fix

// before: stale override pointing at missing binary
export ASPIRE_REPO_ROOT=/old/checkout
// after: remove the override and re-extract the bundle
unset ASPIRE_REPO_ROOT
aspire setup --force
Defensive patterns

Strategy: validation

Validate before calling

// Run before requesting a profile capture
var managedPath = Environment.GetEnvironmentVariable("ASPIRE_REPO_ROOT") is string root
    ? Path.Combine(root, "artifacts", "bin", "aspire-managed")
    : null;
if (managedPath is not null && !File.Exists(managedPath))
{
    Console.Error.WriteLine($"Dashboard binary missing at {managedPath}; run 'aspire setup --force'.");
}

Try / catch

try
{
    await captureService.StartAsync(options, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("aspire-managed"))
{
    Console.Error.WriteLine("Bundle incomplete — running 'aspire setup --force'...");
}

Prevention

When it happens

Trigger: Running a profiling capture (e.g. 'aspire ... --capture-profile') when: the bundle layout lease's GetManagedPath() returns a non-existent path, the ASPIRE_REPO_ROOT env var points at a checkout without the binary, or the managed-path override env var points to a missing file.

Common situations: Partial or corrupted CLI bundle extraction; user deleted bundle cache directories; ASPIRE_REPO_ROOT pointing to a repo without a built aspire-managed binary; stale environment override variables left over from earlier experiments; interrupted 'aspire setup' leaving an incomplete bundle.

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/5ae87d66f568c376. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Profiling/ProfileCaptureService.cs:79

        var managedPath = ResolveManagedPathOverride(configuration);
        BundleLayoutLease? layoutLease = null;
        if (managedPath is null)
        {
            layoutLease = await bundleService.EnsureExtractedAndAcquireLayoutAsync("cli", "profile-dashboard", cancellationToken).ConfigureAwait(false);
            var layout = layoutLease?.Layout;
            managedPath = layout?.GetManagedPath();
        }

        // `ASPIRE_REPO_ROOT` is the shared opt-in for repo-local assets. Avoid independently
        // walking from the command directory or process path here, because installed CLIs should not
        // accidentally bind to a nearby checkout while profiling unrelated applications.
        managedPath ??= ResolveRepoLocalManagedPath(configuration[BundleDiscovery.RepoRootEnvVar]);

        if (managedPath is null || !File.Exists(managedPath))
        {
            layoutLease?.Dispose();
            throw new InvalidOperationException(DashboardCommandStrings.ManagedBinaryNotFound);
        }

        var outputCollector = new OutputCollector(fileLoggerProvider, "ProfileDashboard");
        var dashboardArgs = new[]
        {
            "dashboard",
            $"--{KnownAspNetCoreConfigNames.Urls}={options.DashboardUrl}",
            $"--{KnownConfigNames.DashboardOtlpGrpcEndpointUrl}={options.OtlpGrpcUrl}",
            $"--{KnownConfigNames.DashboardOtlpHttpEndpointUrl}={options.OtlpHttpUrl}",
            $"--{KnownConfigNames.DashboardUnsecuredAllowAnonymous}=true",
            $"--{KnownConfigNames.DashboardApiEnabled}=true"
        };

        var processOptions = new ProcessInvocationOptions
        {
            StandardOutputCallback = outputCollector.AppendOutput,
            StandardErrorCallback = outputCollector.AppendError
        };

View on GitHub (pinned to 25830f84bd)