microsoft/aspire · error · InvalidOperationException

Dashboard testing is not supported in publish mode.

Error message

Dashboard testing is not supported in publish mode.

What it means

ConfigureDashboardTesting in DistributedApplicationTestingBuilder throws this InvalidOperationException when the test builder runs in publish mode (ExecutionContext.IsPublishMode). Dashboard testing configuration (fixed ports, anonymous access, interactivity suppression) only applies to run mode, so publish-mode execution is rejected rather than misconfigured.

Solutions

  1. Run dashboard tests in run mode; do not enable publish mode in the test host configuration
  2. Use the publish-mode APIs (e.g. builder.CreatePublishModeSnapshot / publishing tests) instead of the dashboard testing builder for deployment validation
  3. Remove env/config that flips IsPublishMode (check for ASPNETCORE / ASPIRE publish switches in test setup)

Example fix

// before
var builder = await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>([], (o, _) => o.EnablePublishMode = true); // publish mode
// after
var builder = await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>(); // run mode, dashboard testing allowed
Defensive patterns

Strategy: try-catch

Validate before calling

var execContext = builder.ExecutionContext;
if (execContext.IsPublishMode) { /* use publishing APIs instead of dashboard testing */ }

Try / catch

try
{
    var builder = await DistributedApplicationTestingBuilder.CreateAsync<Projects.AppHost>();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("publish mode"))
{
    // switch to publish-mode test APIs
}

Prevention

When it happens

Trigger: Creating a DistributedApplicationTestingBuilder whose execution context is publish mode — e.g. tests invoking the publishing pipeline or setting publish-mode environment flags before the dashboard testing configuration is applied.

Common situations: Reusing the testing builder for publish/deployment tests; environment variables (ASPIRE_*/DOTNET_* publish flags) leaking into test host config; mixing run-mode and publish-mode test setups.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Testing/DistributedApplicationTestingBuilder.cs:360

            $"{KnownConfigNames.DashboardFrontendBrowserToken}={browserToken}",
            $"{KnownConfigNames.DashboardResourceServiceClientApiKey}={resourceServiceApiKey}"
        ];
        applicationOptions.Args = hostBuilderOptions.Args;

        hostBuilderOptions.Configuration ??= new();
        AddDashboardTestingConfiguration(hostBuilderOptions.Configuration);
    }

    private static void ConfigureDashboardTesting(IDistributedApplicationBuilder builder, DashboardTestingState dashboardTestingState)
    {
        if (!dashboardTestingState.Enabled)
        {
            return;
        }

        if (builder.ExecutionContext.IsPublishMode)
        {
            throw new InvalidOperationException(Properties.Resources.DashboardTestingPublishModeExceptionMessage);
        }

        // Apply these after the builder has loaded environment variables and command-line arguments so test
        // automation cannot accidentally opt back into fixed ports, anonymous access, or interactivity.
        // Callers can still override runtime settings through the returned builder; constructor-time service
        // selection, including dashboard authentication, has already completed.
        AddDashboardTestingConfiguration(builder.Configuration);

        // Restore the generated browser token if something cleared it. DistributedApplicationBuilder freezes the
        // token into AppHost:BrowserToken during construction, but DashboardOptions does not read that key until the
        // application starts, so AppHost code running between those two points can blank it. DashboardEventHandlers
        // treats a null or empty token as a request for Unsecured frontend authentication, which would silently
        // downgrade the authenticated default this opt-in promises, so the guard mirrors that same emptiness check
        // and leaves any non-empty token, including a deliberately chosen one, alone. This runs after the AppHost
        // entry point has finished configuring, because the builder is not handed back until it reaches Build(), and
        // before the caller sees the builder, so a test that wants the anonymous dashboard can still choose it
        // through the returned builder.
        if (string.IsNullOrEmpty(builder.Configuration["AppHost:BrowserToken"]))

View on GitHub (pinned to 25830f84bd)