microsoft/aspire · error · InvalidOperationException
Azure deployment for
Error message
Azure deployment for {resource.Name} was canceled. What it means
When reconciling a Bicep deployment, Aspire reads the ARM deployment's ProvisioningState. If ARM reports the deployment was Canceled, Aspire persists that terminal state, publishes an 'Azure deployment canceled' state to the dashboard, and throws InvalidOperationException so the resource does not silently re-enter a retry loop. This makes ARM's terminal cancellation visible instead of looping indefinitely.
Solutions
- Check the deployment in the Azure portal (Resource Group > Deployments) to see which operation was canceled and why.
- Delete or clean up the canceled deployment / resource group state, then re-run the app host so a fresh deployment is created.
- If you canceled it intentionally (Ctrl+C during provisioning), simply re-run — but ensure no stale conflicting deployment remains.
- Look for concurrent processes deploying to the same resource group and serialize them; overlapping deployments can cancel each other.
- If cancellation is spurious, inspect activity logs for the caller that issued the cancel request.
Example fix
// before dotnet run --project MyAspireApp.AppHost # repeatedly hits canceled deployment // after az group deployment list -g my-rg -o table # find the canceled deployment az deployment group delete -g my-rg --name <stale-deployment> dotnet run --project MyAspireApp.AppHost # fresh deployment succeeds
Defensive patterns
Strategy: try-catch
Validate before calling
var deployment = await armClient.GetArmResource(deploymentId).GetAsync(ct);
if (string.Equals(deployment.Value.Data.ProvisioningState, "Canceled", StringComparison.OrdinalIgnoreCase))
{
// reconcile stale deployment state before re-running provisioning
} Try / catch
try
{
await provisioner.GetOrCreateResourceAsync(resource, context, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("was canceled"))
{
logger.LogWarning(ex, "Azure deployment was canceled (ARM terminal state). Check portal deployments, clean up, and re-run.");
} Prevention
- Don't cancel deployments mid-run (avoid killing the AppHost during active provisioning; stop it gracefully).
- Check Resource Group > Deployments in the portal before re-running to spot stale canceled deployments.
- Avoid running multiple app hosts / pipelines deploying to the same resource group concurrently.
- Treat the dashboard's 'Azure deployment canceled' state as terminal and investigate before retrying.
When it happens
Trigger: Calling GetOrCreateResourceAsync / ReconcileDeploymentStateAsync (or TryAdoptActiveDeploymentConflictAsync when adopting an existing active deployment) against a deployment whose latest ARM provisioning state is 'Canceled' — typically because someone or another process canceled the deployment in the Azure portal, or a Ctrl+C/timeout canceled it mid-provisioning.
Common situations: A developer canceled a deployment in the Azure portal or via CLI; an upstream ARM timeout or parallel conflicting deployment caused cancellation; a previous run of the app host was terminated and its deployment canceled, and a new run now reconciles against that canceled deployment.
Related errors
- Azure deployment for
- AzureProvisioningFailureException (deployment failure…
- Deployment failed
- A of type cannot be assigned to a BicepValue< >.
- An Azure principal parameter was not supplied a value…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/b0fef3ca6423ea2e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure/Provisioning/Provisioners/BicepProvisioner.cs:424
{
// Successful adoption replays the deployment outputs into the resource
// state exactly as normal provisioning would.
return await ConfigureSucceededReconciledDeploymentAsync(
resource,
stateSection,
deploymentId,
deployment.Outputs,
currentLocation,
cancellationToken).ConfigureAwait(false);
}
if (string.Equals(deployment.ProvisioningState, DeploymentStateProvisioningStateCanceled, StringComparisons.AzureProvisioningState))
{
// Preserve ARM's terminal cancellation so the dashboard explains why this
// resource stopped instead of silently retrying.
await PersistReconciledProvisioningStateAsync(stateSection, DeploymentStateProvisioningStateCanceled, cancellationToken).ConfigureAwait(false);
await PublishReconciledTerminalStateAsync(resource, AzureProvisioningStrings.ResourceStateAzureDeploymentCanceled).ConfigureAwait(false);
throw new InvalidOperationException($"Azure deployment for {resource.Name} was canceled.");
}
if (string.Equals(deployment.ProvisioningState, DeploymentStateProvisioningStateFailed, StringComparisons.AzureProvisioningState))
{
// Preserve ARM's terminal failure for the same reason as cancellation:
// this is the outcome of the adopted deployment.
await PersistReconciledProvisioningStateAsync(stateSection, DeploymentStateProvisioningStateFailed, cancellationToken).ConfigureAwait(false);
await PublishReconciledTerminalStateAsync(resource, AzureProvisioningStrings.ResourceStateAzureDeploymentFailed).ConfigureAwait(false);
throw new InvalidOperationException($"Azure deployment for {resource.Name} failed.");
}
return false;
}
private async Task PersistReconciledProvisioningStateAsync(DeploymentStateSection stateSection, string provisioningState, CancellationToken cancellationToken)
{
stateSection.Data[DeploymentStateProvisioningStateKey] = provisioningState;
await deploymentStateManager.SaveSectionAsync(stateSection, cancellationToken).ConfigureAwait(false);View on GitHub (pinned to 25830f84bd)