microsoft/aspire · error

No Azure deployment state was found for AKS environment

Error message

No Azure deployment state was found for AKS environment '{Name}'. Cluster cleanup cannot run without an isolated kubeconfig.

What it means

During AKS environment destroy, GetAksCredentialsForDestroyAsync reads the persisted 'Azure:Deployments:<Name>' state section to recover the deployed cluster's resource id so it can fetch a kubeconfig and clean up the cluster. This error is thrown when the state store has no deployment outputs for this environment, so cleanup cannot proceed safely with an isolated kubeconfig.

Solutions

  1. Deploy the environment at least once successfully before destroying, so the deployment state is persisted
  2. Ensure the destroy command targets the same environment name used during deployment (check 'Azure:Deployments:<Name>' key)
  3. Restore or point the destroy run at the correct deployment state store/backend used by the original deployment
  4. If the cluster exists but state is unrecoverable, delete the resource group/cluster directly in Azure instead of through the pipeline cleanup step

Example fix

// before (destroy with mismatched name)
builder.AddAzureKubernetesEnvironment("prod-aks"); // deployed as "aks-env"
// after
builder.AddAzureKubernetesEnvironment("aks-env"); // same name as the deployed state
Defensive patterns

Strategy: validation

Validate before calling

var section = await deploymentStateManager.AcquireSectionAsync($"Azure:Deployments:{Name}", ct);
bool canDestroy = section.Data.Count > 0;

Try / catch

try
{
    await pipeline.DestroyAsync(...);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("No Azure deployment state"))
{
    // No prior deployment state; clean up in Azure directly (resource group deletion) instead.
}

Prevention

When it happens

Trigger: Running aspire destroy / pipeline destroy for an AKS environment whose name has no 'Azure:Deployments:<Name>' section in the deployment state store — e.g. the deployment never completed, the state was deleted, or the environment name doesn't match the one used at deploy time.

Common situations: Destroying an environment that was never successfully deployed; a stale or cleared state store (local state files removed, different state backend); renaming the AKS environment resource between deploy and destroy.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they 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/6c91cd412aa4f1c6. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Azure.Kubernetes/AzureKubernetesEnvironmentResource.AksPipeline.cs:373

            {
                await getCredsTask.FailAsync(
                    $"Failed to fetch AKS credentials: {ex.Message}",
                    context.CancellationToken).ConfigureAwait(false);
                throw;
            }
        }
    }

    private async Task GetAksCredentialsForDestroyAsync(PipelineStepContext context)
    {
        var deploymentStateManager = context.Services.GetRequiredService<IDeploymentStateManager>();
        var deploymentStateSection = await deploymentStateManager
            .AcquireSectionAsync($"Azure:Deployments:{Name}", context.CancellationToken)
            .ConfigureAwait(false);

        if (deploymentStateSection.Data.Count == 0)
        {
            throw new InvalidOperationException(
                $"No Azure deployment state was found for AKS environment '{Name}'. " +
                "Cluster cleanup cannot run without an isolated kubeconfig.");
        }

        // Azure deployment outputs are persisted as a JSON string with the ARM output shape:
        //   {
        //     "id": { "type": "String", "value": "/subscriptions/.../managedClusters/aks-abc123" },
        //     "name": { "type": "String", "value": "aks-abc123" }
        //   }
        // Read it directly because the provisioning step that normally populates Outputs is not
        // part of a fresh destroy process.
        ResourceIdentifier? clusterResourceId;
        try
        {
            clusterResourceId = GetPersistedAksResourceId(deploymentStateSection.Data);
        }
        catch (Exception ex) when (ex is not OperationCanceledException)
        {

View on GitHub (pinned to 25830f84bd)