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
- Run 'aspire setup --force' to re-extract a complete CLI bundle.
- Reinstall the Aspire CLI if re-extraction does not restore aspire-managed.
- 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).
- 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
- Never manually delete or edit the CLI bundle cache directory.
- Remove stale ASPIRE_REPO_ROOT / managed-path overrides when not doing repo-local development.
- Run 'aspire setup --force' after upgrading the CLI if layout errors appear.
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
- Dashboard did not become ready within the expected time.
- Dashboard exited with exit code
- Failed to start Aspire dashboard
- aspire-managed not found in layout.
- Bundle layout not found. Cannot perform NuGet restore in…
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)