AZD Errors
Deployment Runtime Errors
These errors occur during azd up execution:
| Error | Cause | Resolution |
|---|---|---|
unknown flag: --location | azd up doesn't accept --location | Use azd env set AZURE_LOCATION <region> before azd up |
| Provision failed | Bicep template errors | Check detailed error in output |
| Deploy failed | Build or Docker errors | Check build logs |
| Package failed | Missing Dockerfile or deps | Verify Dockerfile exists and dependencies |
| Quota exceeded | Subscription limits | Request increase or change region |
PrincipalId '...' has type 'ServicePrincipal', which is different from specified PrincipalType 'User' | Base template RBAC assigns roles with principalType: 'User' but deploying identity is a service principal (CI/CD) | Set allowUserIdentityPrincipal: false in the storageEndpointConfig variable in infra/main.bicep. Do NOT try clearing AZURE_PRINCIPAL_ID — azd repopulates it. See Principal Type Mismatch. |
ImagePullBackOff or azd up hangs during provision for Container Apps | Container App references an image that doesn't exist in ACR yet | See Container Apps Bootstrap Problem |
unauthorized: authentication required on docker push to ACR | ACR auth token expired or scoped incorrectly | See ACR Authentication Failures |
could not determine container registry endpoint | Missing AZURE_CONTAINER_REGISTRY_ENDPOINT | See Missing Container Registry Variables |
map has no entry for key "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID" | Missing managed identity env vars | See Missing Container Registry Variables |
map has no entry for key "MANAGED_IDENTITY_CLIENT_ID" | Missing managed identity client ID | See Missing Container Registry Variables |
Operation expired / revision creation timeout (900s) | RBAC propagation delay — Container App's managed identity doesn't have AcrPull on ACR yet | See Container App Revision Timeout |
found '2' resources tagged with 'azd-service-name: <name>' | Previous deployment left duplicate-tagged resources in same RG | Preferred: Create fresh env with azd env new <new-name> --no-prompt, set subscription/location, redeploy. Alternative: Delete conflicting resources (requires ask_user). |
Literal {{ .Env.* }} in Terraform errors | azd does not interpolate template variables in .tfvars.json | See Unresolved Terraform Template Variables |
ℹ️ Pre-flight validation: Run
azure-validatebefore deployment to catch configuration errors early. See Pre-Deploy Checklist.
Container App Revision Timeout
Symptom: azd up provisions infrastructure successfully but the Container App revision creation times out after ~900 seconds. The Container App enters a Failed provisioning state with no active revision. The azd output shows Operation expired or The operation did not complete within the permitted time.
Cause: Azure RBAC propagation delay. When azd up runs both azd provision and azd deploy in a single step:
- Bicep creates the Container App with a system-assigned managed identity and a public placeholder image
- Bicep creates an
AcrPullrole assignment for that identity on ACR in a separate module using the two-phase deployment pattern azd deployimmediately pushes the real image and creates a new Container App revision- The revision tries to pull the image from ACR, but the
AcrPullrole assignment hasn't propagated yet (can take 1–5 minutes) - The image pull fails repeatedly until the 900-second timeout is reached
Solution:
- Verify the Container App state:
az containerapp show --name <app-name> --resource-group <resource-group> \
--query "{provisioningState:properties.provisioningState, latestRevision:properties.latestRevisionName}" -o json- Confirm the AcrPull role exists (it may have propagated by now):
PRINCIPAL_ID=$(az containerapp identity show --name <app-name> --resource-group <resource-group> --query principalId -o tsv)
az role assignment list --scope $(az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv) \
--assignee-object-id "$PRINCIPAL_ID" --query "[].roleDefinitionName" -o tsvPowerShell:
$PrincipalId = az containerapp identity show --name <app-name> --resource-group <resource-group> --query principalId -o tsv
$AcrScope = az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv
az role assignment list --scope $AcrScope --assignee-object-id $PrincipalId --query "[].roleDefinitionName" -o tsv- If AcrPull is missing, assign it:
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--assignee-principal-type ServicePrincipal \
--role AcrPull \
--scope $(az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv)PowerShell:
$AcrScope = az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv
az role assignment create `
--assignee-object-id $PrincipalId `
--assignee-principal-type ServicePrincipal `
--role AcrPull `
--scope $AcrScope- Wait for propagation, then redeploy:
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr show --name <acr-name> --resource-group <resource-group> --query loginServer -o tsv)
for attempt in 1 2 3 4 5; do
echo "Waiting for RBAC propagation (attempt $attempt/5)..."
sleep 60
if azd deploy --no-prompt; then
echo "Deployment succeeded after RBAC propagation."
break
fi
if [ "$attempt" -eq 5 ]; then
echo "Deployment still failing after 5 minutes. Re-check AcrPull assignment and Container App revision status."
exit 1
fi
donePowerShell:
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr show --name <acr-name> --resource-group <resource-group> --query loginServer -o tsv)
for ($attempt = 1; $attempt -le 5; $attempt++) {
Write-Output "Waiting for RBAC propagation (attempt $attempt/5)..."
Start-Sleep -Seconds 60
azd deploy --no-prompt
if ($LASTEXITCODE -eq 0) {
Write-Output "Deployment succeeded after RBAC propagation."
break
}
if ($attempt -eq 5) {
Write-Output "Deployment still failing after 5 minutes. Re-check AcrPull assignment and Container App revision status."
exit 1
}
}💡 Prevention: To avoid this in future deployments, ensure the Bicep template includes the
AcrPullrole assignment withprincipalType: 'ServicePrincipal', and consider usingazd provision+azd deployas separate steps instead ofazd upto allow RBAC propagation time between infrastructure creation and app deployment.
Container Apps Bootstrap Problem
Symptom: azd up hangs or fails during provisioning with ImagePullBackOff, or the Container App cannot start because the referenced image doesn't exist in ACR yet.
Cause: The Bicep template creates the Container App referencing an ACR image, but that image doesn't exist until azd deploy builds and pushes it. This chicken-and-egg problem blocks provisioning.
Solution — use two-phase deployment:
# Phase 1: Provision infrastructure (Container App uses placeholder image)
azd provision --no-prompt
# Phase 2: Build, push, and update Container App with real image
azd deploy --no-prompt⚠️ This requires the Bicep template to use a placeholder image parameter (e.g.,
mcr.microsoft.com/azuredocs/containerapps-helloworld:latest) so provisioning succeeds without the app image. If the Bicep hardcodes the ACR image reference, update it to accept acontainerImageNameparameter with a placeholder default before provisioning.
⚠️ Do NOT repeatedly poll a hanging
azd up— if there is no provisioning progress or you continue to seeImagePullBackOffevents for several minutes during a Container Apps deployment, stop it and switch to the two-phase approach above.
ACR Authentication Failures
Symptom: docker push fails with unauthorized: authentication required even after az acr login succeeds.
Solution — try these methods in order:
# Method 1: AAD-based login (preferred)
az acr login --name <acr-name>
docker push <acr-name>.azurecr.io/<image>:<tag>
# Method 2: Admin credentials (fallback)
ACR_USER=$(az acr credential show --name <acr-name> --query username -o tsv)
ACR_PASS=$(az acr credential show --name <acr-name> --query "passwords[0].value" -o tsv)
docker login <acr-name>.azurecr.io -u "$ACR_USER" -p "$ACR_PASS"
docker push <acr-name>.azurecr.io/<image>:<tag>PowerShell (Method 2):
$AcrUser = az acr credential show --name <acr-name> --query username -o tsv
$AcrPass = az acr credential show --name <acr-name> --query "passwords[0].value" -o tsv
docker login <acr-name>.azurecr.io -u $AcrUser -p $AcrPass
docker push <acr-name>.azurecr.io/<image>:<tag>💡 Tip: Prefer
azd deployover manualdocker push— azd handles ACR authentication automatically.
Missing Container Registry Variables
Symptom: Errors during azd deploy about missing container registry or managed identity environment variables:
ERROR: could not determine container registry endpoint, ensure 'registry' has been set in the docker options or 'AZURE_CONTAINER_REGISTRY_ENDPOINT' environment variable has been setOr:
ERROR: failed executing template file: template: manifest template:6:14: executing "manifest template" at <.Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID>: map has no entry for key "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID"Or:
ERROR: failed executing template file: template: manifest template:39:26: executing "manifest template" at <.Env.MANAGED_IDENTITY_CLIENT_ID>: map has no entry for key "MANAGED_IDENTITY_CLIENT_ID"Cause: This typically occurs with .NET Aspire projects using azd "limited mode" (in-memory infrastructure generation without explicit infra/ folder). The azd provision command creates the Azure Container Registry and Managed Identity resources but doesn't automatically populate the environment variables that azd deploy needs to reference them.
⚠️ Prevention is Better: For .NET Aspire projects, this issue should be addressed PROACTIVELY before deployment by setting up environment variables after
azd initbut beforeazd up. This avoids deployment failures entirely.
Solution:
After azd provision succeeds, manually set the missing environment variables by querying the provisioned resources:
# Get the resource group name (typically rg-{environment-name})
azd env get-values
# Set container registry endpoint
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr list --resource-group <resource-group-name> --query "[0].loginServer" -o tsv)
# Set managed identity resource ID
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID $(az identity list --resource-group <resource-group-name> --query "[0].id" -o tsv)
# Set managed identity client ID
azd env set MANAGED_IDENTITY_CLIENT_ID $(az identity list --resource-group <resource-group-name> --query "[0].clientId" -o tsv)PowerShell:
# Set container registry endpoint
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr list --resource-group <resource-group-name> --query "[0].loginServer" -o tsv)
# Set managed identity resource ID
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID (az identity list --resource-group <resource-group-name> --query "[0].id" -o tsv)
# Set managed identity client ID
azd env set MANAGED_IDENTITY_CLIENT_ID (az identity list --resource-group <resource-group-name> --query "[0].clientId" -o tsv)After setting these variables, retry the deployment:
azd deploy --no-prompt💡 Tip: This issue is specific to Aspire limited mode. Manually setting these environment variables after
azd provisionis the recommended workaround.
Unresolved Terraform Template Variables
Symptom: Terraform receives literal Go-style template strings instead of resolved values during azd provision:
Error: Invalid value for variable "environment_name"
The value "{{ .Env.AZURE_ENV_NAME }}" is not valid.Or Terraform silently uses the literal string, causing resource naming failures, state conflicts, and cascading errors that lead to deployment timeouts.
Cause: azd reads infra/main.tfvars.json, substitutes ${VAR} references using its built-in envsubst, and passes the resolved file to Terraform via -var-file=. Go-style {{ .Env.* }} variables are only processed in azure.yaml and service manifests — they are NOT interpolated in .tfvars.json or any Terraform variable files. If azure-prepare generated a main.tfvars.json with Go-style template expressions, those literal strings are passed to Terraform.
Solution:
- Fix the syntax in
infra/main.tfvars.json— replace Go-style{{ .Env.* }}with${VAR}:
{
"environment_name": "${AZURE_ENV_NAME}",
"location": "${AZURE_LOCATION}",
"subscription_id": "${AZURE_SUBSCRIPTION_ID}"
}- Or use
TF_VAR_*environment variables if you don't havemain.tfvars.json:
azd env set TF_VAR_environment_name "$(azd env get-value AZURE_ENV_NAME)"
azd env set TF_VAR_location "$(azd env get-value AZURE_LOCATION)"
azd env set TF_VAR_subscription_id "$(azd env get-value AZURE_SUBSCRIPTION_ID)"- Ensure
variables.tfdeclares all required variables:
variable "environment_name" { type = string }
variable "location" { type = string }- Re-run deployment:
azd up --no-prompt⚠️ Prevention: This issue should be caught by
azure-validateStep 10 (Template Variable Resolution Check) before deployment. If you encounter it, re-run validation after fixing.
Retry
After fixing the issue:
azd up --no-promptPrincipal Type Mismatch
Symptom: azd up fails during provisioning with:
PrincipalId '...' has type 'ServicePrincipal', which is different from specified PrincipalType 'User'Cause: Many AZD templates (e.g., functions-quickstart-python-http-azd) include RBAC role assignments for the deploying user with hardcoded principalType: 'User'. This is controlled by an allowUserIdentityPrincipal flag in main.bicep's storageEndpointConfig variable. When deploying from CI/CD with a service principal, azd sets AZURE_PRINCIPAL_ID to that service principal's object ID, but the Bicep still tries to create a role assignment with principalType: 'User', causing ARM to reject it.
Solution:
In infra/main.bicep, find the storageEndpointConfig variable and set allowUserIdentityPrincipal to false:
var storageEndpointConfig = {
enableBlob: true
enableQueue: false
enableTable: false
enableFiles: false
allowUserIdentityPrincipal: false // Set to false for service principal deployments
}⚠️ Do NOT try to fix this by running
azd env set AZURE_PRINCIPAL_ID "". TheazdCLI repopulates this value from the current auth context, so clearing it has no effect.
Cleanup (DESTRUCTIVE)
azd down --force --purge⚠️ Permanently deletes ALL resources including databases and Key Vaults.