{"record":{"id":"512d2820e134f6be","repo":"microsoft/aspire","slug":"azure-provisioning-failure-with-published-failure-details","errorCode":null,"errorMessage":"Azure provisioning failure with published failure details.","messagePattern":"Azure provisioning failure with published failure details\\.","errorType":"exception","errorClass":"AzureProvisioningFailureException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure/AzureProvisioningController.cs","lineNumber":1982,"sourceCode":"            // with the same generated name. ARM only reports this conflict once the live vault is already\n            // absent, so issue the purge directly rather than starting another delete that can wait on\n            // the same tombstone and delay the retry.\n            var purged = await PurgeDeletedKeyVaultAsync(\n                armClient,\n                keyVaultResourceId,\n                intent.ResourceName,\n                effectiveLocation,\n                currentContext.Location,\n                allowTimeout: false,\n                cancellationToken).ConfigureAwait(false);\n            if (!purged)\n            {\n                var failureDetails = AzureProvisioningFailureDetails.CreateKeyVaultDeletedStateTombstoneNotFound(\n                    keyVaultResourceIdentifier.Name,\n                    keyVaultResourceId,\n                    GetKeyVaultPurgeLocations(effectiveLocation, currentContext.Location));\n                await PublishSyntheticProvisioningFailureAsync(model, targetResources, failureDetails).ConfigureAwait(false);\n                throw new AzureProvisioningFailureException(failureDetails, ex);\n            }\n\n            await ResetResourcesAsync(model, targetResources, preserveOverrides: true, cancellationToken).ConfigureAwait(false);\n            return await EnsureProvisionedOrThrowAsync(model, targetResources, cancellationToken).ConfigureAwait(false);\n        }\n    }\n\n    // Key Vault is special because deleting a vault leaves a location-scoped soft-delete tombstone.\n    // A later create with the same vault name can fail until that tombstone is purged, even though\n    // the live resource no longer exists. Detect that specific provisioning failure so reprovision\n    // can purge the recoverable vault for the same target resource ID and retry once.\n    private static bool TryGetKeyVaultSoftDeleteConflictResourceId(Exception exception, out string keyVaultResourceId)\n    {\n        keyVaultResourceId = string.Empty;\n        if (AzureProvisioningFailureDetails.TryCreate(exception, AzureProvisioningFailureDetails.ProvisionOperation) is not { } failure ||\n            !string.Equals(failure.ResourceType, KeyVaultVaultResourceType, StringComparisons.AzureResourceType) ||\n            string.IsNullOrWhiteSpace(failure.TargetResourceId) ||\n            !ResourceIdentifier.TryParse(failure.TargetResourceId, out var parsedResourceId) ||","sourceCodeStart":1964,"sourceCodeEnd":2000,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure/AzureProvisioningController.cs#L1964-L2000","documentation":"During Key Vault provisioning the controller detected the vault exists only as a soft-deleted tombstone that could not be located. It publishes a synthetic failure detail explaining the situation and throws AzureProvisioningFailureException wrapping the original exception.","triggerScenarios":"Creating a Key Vault with a name whose soft-deleted tombstone exists in a different region or subscription so the tombstone can't be resolved; retrying provisioning after a vault was deleted and purge-protection prevented real deletion.","commonSituations":"Name collision with a previously deleted vault; moving a vault across regions while soft-delete retention (7-90 days) is active; CI recreating environments with deterministic vault names.","solutions":["Choose a different Key Vault name to avoid the reserved soft-deleted name","Purge the soft-deleted vault in its recorded location (az keyvault purge) or wait for retention to expire","Follow the published failure details to locate and recover/purge the tombstone"],"exampleFix":"// before\nbuilder.AddAzureKeyVault(\"my-vault\"); // name reserved by soft-deleted vault\n// after\nbuilder.AddAzureKeyVault(\"my-vault-2\");","handlingStrategy":"validation","validationCode":"// before provisioning, check for reserved soft-deleted vault names:\n// az keyvault list-deleted --query \"[?name=='my-vault']\"","typeGuard":null,"tryCatchPattern":"try { await EnsureProvisionedAsync(...); } catch (AzureProvisioningFailureException ex) { /* read ex failure details; purge tombstone or pick a new vault name */ }","preventionTips":["Check az keyvault list-deleted before reusing a vault name","Use unique vault names per environment/pipeline","Do not delete and recreate vaults with the same name in different regions"],"tags":["azure","key-vault","provisioning","soft-delete","failure-details"],"backgroundTag":"api-error-response","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"}