microsoft/aspire · error · AzureProvisioningFailureException

AzureProvisioningFailureException (deployment failure…

Error message

AzureProvisioningFailureException (deployment failure details)

What it means

During GetOrCreateResourceAsync, when the ARM deployment creation fails, Aspire collects deployment-operation failure details (from ARM's deployment operations), logs them, updates the resource state to 'Azure deployment failed' with the enriched failure details, and throws AzureProvisioningFailureException wrapping the original exception and details. This gives the developer a single exception carrying per-operation ARM error codes/messages instead of a bare RequestFailedException.

Solutions

  1. Read AzureProvisioningFailureException.FailureDetails (and the logged output) for the exact ARM error code and target resource; fix that specific error.
  2. Check the deployment error details in the Azure portal (Resource Group > Deployments > failed deployment) if the exception details are insufficient.
  3. Fix common causes: correct parameter values, register missing resource providers, resolve quota/naming conflicts, grant required RBAC roles.
  4. Re-run the app host after fixing; the deployment is retried on the next provisioning run.
  5. Catch AzureProvisioningFailureException in automation to access structured failure details programmatically instead of parsing logs.

Example fix

// before
try
{
    await GetOrCreateResourceAsync(resource, context);
}
catch (Exception ex)
{
    logger.LogError(ex, "provisioning failed");   // loses ARM per-operation detail
}

// after
try
{
    await GetOrCreateResourceAsync(resource, context);
}
catch (AzureProvisioningFailureException ex)
{
    foreach (var detail in ex.FailureDetails.Operations)
    {
        logger.LogError("{Target}: {Code} - {Message}", detail.Target, detail.Code, detail.Message);
    }
}
Defensive patterns

Strategy: try-catch

Type guard

if (ex is AzureProvisioningFailureException apfe)
{
    foreach (var op in apfe.FailureDetails.Operations)
    {
        Console.WriteLine($"{op.Target}: {op.Status} {op.Code}: {op.Message}");
    }
}

Try / catch

try
{
    await provisioner.GetOrCreateResourceAsync(resource, context, ct);
}
catch (AzureProvisioningFailureException ex)
{
    logger.LogError(ex, "Deployment failed. ARM operations: {Details}", ex.FailureDetails);
}

Prevention

When it happens

Trigger: A Bicep deployment submitted by GetOrCreateResourceAsync fails: ARM returns a provisioning failure (template validation error, resource-level error, quota, naming conflict, RP not registered, auth/permission failure on a nested resource). The exception is thrown after LogProvisioningFailure with AzureProvisioningFailureDetails populated from deployment operations.

Common situations: Invalid Bicep template or parameters; region capacity/quota limits; resource name already taken or invalid characters; missing role assignments/permissions for managed identities; unregistered resource providers; wrong subscription or location values in provisioning options.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Azure/Provisioning/Provisioners/BicepProvisioner.cs:665

            var failureDetails = AzureProvisioningFailureDetails.FromRequestFailedException(ex, AzureProvisioningFailureDetails.ProvisionOperation);
            if (!failureDetails.IsLocationAvailabilityFailure)
            {
                LogProvisioningFailure(resourceLogger, failureDetails);
                throw;
            }

            failureDetails = await EnrichFailureDetailsAsync(failureDetails, context, effectiveLocation, cancellationToken).ConfigureAwait(false);
            if (context.ExecutionContext.IsRunMode)
            {
                await notificationService.PublishUpdateAsync(resource, state => state with
                {
                    State = new(AzureProvisioningStrings.ResourceStateAzureDeploymentFailed, KnownResourceStateStyles.Error),
                    Properties = failureDetails.SetResourceProperties(WithoutDeploymentOperationProperties(state.Properties), AzureProvisioningFailureDetails.ProvisionOperation)
                }).ConfigureAwait(false);
            }

            LogProvisioningFailure(resourceLogger, failureDetails);
            throw new AzureProvisioningFailureException(failureDetails, ex);
        }

        // Run mode keeps persisting deployment state and final diagnostics after cancellation so
        // Ctrl+C leaves enough information for recovery. Publish/deploy should still honor the
        // caller's cancellation token because those operations are command-scoped.
        var statePersistenceCancellationToken = context.ExecutionContext.IsRunMode ? CancellationToken.None : cancellationToken;
        DeploymentStateSection? stateSection = null;
        string? locationOverride = null;

        if (context.ExecutionContext.IsRunMode)
        {
            var sectionName = $"Azure:Deployments:{resource.Name}";
            stateSection = await deploymentStateManager.AcquireSectionAsync(sectionName, statePersistenceCancellationToken).ConfigureAwait(false);
            locationOverride = stateSection.Data[AzureProvisioningController.LocationOverrideKey]?.GetValue<string>();
            UpdateDeploymentState(stateSection, locationOverride, deploymentId, parameters, outputObj: null, scope, checksum, effectiveLocation, DeploymentStateProvisioningStateRunning);
            await deploymentStateManager.SaveSectionAsync(stateSection, statePersistenceCancellationToken).ConfigureAwait(false);
        }
        // Resolve the deployment URL before waiting for the operation to complete

View on GitHub (pinned to 25830f84bd)