{"record":{"id":"4a1169e9c091c4b0","repo":"microsoft/aspire","slug":"cannot-perform-destructive-operation-without-confirmation","errorCode":null,"errorMessage":"Cannot perform destructive operation without confirmation. Use --yes to skip the confirmation prompt in non-interactive mode.","messagePattern":"Cannot perform destructive operation without confirmation\\. Use --yes to skip the confirmation prompt in non-interactive mode\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure/AzureEnvironmentResource.cs","lineNumber":251,"sourceCode":"        var subscriptionId = azureStateSection.Data[\"SubscriptionId\"]?.ToString();\n\n        if (string.IsNullOrEmpty(resourceGroupName) || string.IsNullOrEmpty(subscriptionId))\n        {\n            await context.ReportingStep.CompleteAsync(\n                \"No Azure deployment state found. Nothing to destroy.\",\n                CompletionState.Completed,\n                context.CancellationToken).ConfigureAwait(false);\n            return;\n        }\n\n        // Fail fast in non-interactive mode without --yes before doing any Azure work\n        var options = context.Services.GetRequiredService<IOptions<PipelineOptions>>();\n        if (!options.Value.SkipConfirmation)\n        {\n            var interactionService = context.Services.GetRequiredService<IInteractionService>();\n            if (!interactionService.IsAvailable)\n            {\n                throw new InvalidOperationException(\n                    \"Cannot perform destructive operation without confirmation. Use --yes to skip the confirmation prompt in non-interactive mode.\");\n            }\n        }\n\n        var credential = tokenCredentialProvider.TokenCredential;\n        var armClient = armClientProvider.GetArmClient(credential, subscriptionId);\n        var (subscription, _) = await armClient.GetSubscriptionAndTenantAsync(context.CancellationToken).ConfigureAwait(false);\n\n        var resourceGroups = subscription.GetResourceGroups();\n\n        IResourceGroupResource resourceGroup;\n        try\n        {\n            var rgResponse = await resourceGroups.GetAsync(resourceGroupName, context.CancellationToken).ConfigureAwait(false);\n            resourceGroup = rgResponse.Value;\n        }\n        catch (RequestFailedException ex) when (ex.Status == 404)\n        {","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure/AzureEnvironmentResource.cs#L233-L269","documentation":"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.","triggerScenarios":"Running aspire destroy (pipeline) in CI or scripts without the --yes flag; interactive prompt unavailable (headless environment) and SkipConfirmation false.","commonSituations":"CI/CD pipelines running destroy non-interactively; containerized or SSH environments lacking an interaction UI; forgetting the flag in automation scripts.","solutions":["Add --yes to the CLI command to acknowledge the destructive operation","Set PipelineOptions.SkipConfirmation = true programmatically for automated pipelines","Run destroy in an interactive terminal if you want the confirmation prompt"],"exampleFix":"// before\naspire destroy\n// after\naspire destroy --yes","handlingStrategy":"validation","validationCode":"if (!options.Value.SkipConfirmation && !interactionService.IsAvailable) { throw/exit with guidance to pass --yes; }","typeGuard":"bool CanDestroy(PipelineOptions o, IInteractionService i) => o.SkipConfirmation || i.IsAvailable;","tryCatchPattern":"try { await DestroyAzureResourcesAsync(...); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"--yes\")) { Console.Error.WriteLine(ex.Message); Environment.Exit(2); }","preventionTips":["Always pass --yes in non-interactive/CI destroy commands","Detect headless environments before invoking destructive operations"],"tags":["azure","cli","destroy","confirmation","safety"],"backgroundTag":"missing-required-flag","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}