microsoft/aspire · critical · InvalidOperationException

The Aspire extension token must be set if…

Error message

The Aspire extension token must be set if ASPIRE_EXTENSION_ENDPOINT is set. Please ensure that ASPIRE_EXTENSION_TOKEN is set

What it means

The ExtensionBackchannel constructor reads the extension auth token from configuration (KnownConfigNames.ExtensionToken). If ASPIRE_EXTENSION_ENDPOINT is configured but ASPIRE_EXTENSION_TOKEN is missing, the token is null and the constructor throws this InvalidOperationException, because connecting to the extension endpoint requires the paired token for authentication.

Solutions

  1. Set the ASPIRE_EXTENSION_TOKEN environment variable to the token provided by the Aspire VS Code extension, then restart the CLI.
  2. Verify both ASPIRE_EXTENSION_ENDPOINT and ASPIRE_EXTENSION_TOKEN are exported in the environment where the CLI runs (echo them to confirm).
  3. If you do not intend to use the extension, unset ASPIRE_EXTENSION_ENDPOINT so the extension backchannel is not initialized.

Example fix

// before
export ASPIRE_EXTENSION_ENDPOINT=https://127.0.0.1:54321

// after
export ASPIRE_EXTENSION_ENDPOINT=https://127.0.0.1:54321
export ASPIRE_EXTENSION_TOKEN=<token-from-extension>
Defensive patterns

Strategy: validation

Validate before calling

if (Environment.GetEnvironmentVariable("ASPIRE_EXTENSION_ENDPOINT") is not null &&
    Environment.GetEnvironmentVariable("ASPIRE_EXTENSION_TOKEN") is null)
{
    throw new InvalidOperationException("ASPIRE_EXTENSION_TOKEN must be set when ASPIRE_EXTENSION_ENDPOINT is set.");
}

Try / catch

try { var bc = new ExtensionBackchannel(logger, target, configuration, null); }
catch (InvalidOperationException ex) when (ex.Message.Contains("token must be set"))
{ /* surface missing ASPIRE_EXTENSION_TOKEN guidance */ }

Prevention

When it happens

Trigger: Constructing ExtensionBackchannel (e.g., during CLI startup wiring) when configuration contains ASPIRE_EXTENSION_ENDPOINT but no ASPIRE_EXTENSION_TOKEN value.

Common situations: Users partially configure the VS Code extension integration: they set the endpoint env var (often exported by the extension) but the token variable is lost — not inherited into a spawned terminal, cleared by a shell profile, or simply never set.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Cli/Backchannel/ExtensionBackchannel.cs:85

    private int _connected;

    public ExtensionBackchannel(ILogger<ExtensionBackchannel> logger, IExtensionRpcTarget target, IConfiguration configuration)
        : this(logger, target, configuration, connectCoreAsyncOverride: null)
    {
    }

    internal ExtensionBackchannel(
        ILogger<ExtensionBackchannel> logger,
        IExtensionRpcTarget target,
        IConfiguration configuration,
        Func<CancellationToken, Task>? connectCoreAsyncOverride)
    {
        _logger = logger;
        _target = target;
        _configuration = configuration;
        _connectCoreAsyncOverride = connectCoreAsyncOverride;
        _token = configuration[KnownConfigNames.ExtensionToken]
                      ?? throw new InvalidOperationException(ErrorStrings.ExtensionTokenMustBeSet);

        AppDomain.CurrentDomain.ProcessExit += (_, _) =>
        {
            if (Volatile.Read(ref _connected) == 0)
            {
                return;
            }

            try
            {
                StopDebuggingAsync().GetAwaiter().GetResult();
            }
            catch
            {
                // This may fail if the extension is deactivated before the aspire cli process is stopped
                // or if an active debug session is not occurring. Both of these are fine, we just want to
                // ensure we try to stop the debug session if one is active.
            }

View on GitHub (pinned to 25830f84bd)