microsoft/aspire · error · InvalidOperationException

Cannot perform destructive operation without confirmation…

Error message

Cannot perform destructive operation without confirmation. Use --yes to skip the confirmation prompt in non-interactive mode.

What it means

DestroyAzureResourcesAsync performs a destructive deployment-state deletion and requires explicit confirmation. In non-interactive mode there is no way to prompt, so when --yes (SkipConfirmation) was not supplied and no interaction service exists, it throws to prevent unconfirmed data loss.

Solutions

  1. Add --yes to the CLI command to acknowledge the destructive operation
  2. Set PipelineOptions.SkipConfirmation = true programmatically for automated pipelines
  3. Run destroy in an interactive terminal if you want the confirmation prompt

Example fix

// before
aspire destroy
// after
aspire destroy --yes
Defensive patterns

Strategy: validation

Validate before calling

if (!options.Value.SkipConfirmation && !interactionService.IsAvailable) { throw/exit with guidance to pass --yes; }

Type guard

bool CanDestroy(PipelineOptions o, IInteractionService i) => o.SkipConfirmation || i.IsAvailable;

Try / catch

try { await DestroyAzureResourcesAsync(...); } catch (InvalidOperationException ex) when (ex.Message.Contains("--yes")) { Console.Error.WriteLine(ex.Message); Environment.Exit(2); }

Prevention

When it happens

Trigger: Running aspire destroy (pipeline) in CI or scripts without the --yes flag; interactive prompt unavailable (headless environment) and SkipConfirmation false.

Common situations: CI/CD pipelines running destroy non-interactively; containerized or SSH environments lacking an interaction UI; forgetting the flag in automation scripts.

Understand the failure class

Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Azure/AzureEnvironmentResource.cs:251

        var subscriptionId = azureStateSection.Data["SubscriptionId"]?.ToString();

        if (string.IsNullOrEmpty(resourceGroupName) || string.IsNullOrEmpty(subscriptionId))
        {
            await context.ReportingStep.CompleteAsync(
                "No Azure deployment state found. Nothing to destroy.",
                CompletionState.Completed,
                context.CancellationToken).ConfigureAwait(false);
            return;
        }

        // Fail fast in non-interactive mode without --yes before doing any Azure work
        var options = context.Services.GetRequiredService<IOptions<PipelineOptions>>();
        if (!options.Value.SkipConfirmation)
        {
            var interactionService = context.Services.GetRequiredService<IInteractionService>();
            if (!interactionService.IsAvailable)
            {
                throw new InvalidOperationException(
                    "Cannot perform destructive operation without confirmation. Use --yes to skip the confirmation prompt in non-interactive mode.");
            }
        }

        var credential = tokenCredentialProvider.TokenCredential;
        var armClient = armClientProvider.GetArmClient(credential, subscriptionId);
        var (subscription, _) = await armClient.GetSubscriptionAndTenantAsync(context.CancellationToken).ConfigureAwait(false);

        var resourceGroups = subscription.GetResourceGroups();

        IResourceGroupResource resourceGroup;
        try
        {
            var rgResponse = await resourceGroups.GetAsync(resourceGroupName, context.CancellationToken).ConfigureAwait(false);
            resourceGroup = rgResponse.Value;
        }
        catch (RequestFailedException ex) when (ex.Status == 404)
        {

View on GitHub (pinned to 25830f84bd)