Container Registry Pull Failures: Authentication, Rate Limiting, and Private Registry Access¶
Status: Published
Experiment completed with real data on 2026-05-04.
1. Question¶
When a Container App fails to pull its container image — due to an incorrect registry credential, an expired managed identity token for a private ACR, or a Docker Hub rate limit — how does the failure manifest in system logs and replica provisioning events, and how does the error message differ across failure types?
2. Why this matters¶
Container image pull failures are a top cause of Container App deployment failures, but the error messages are inconsistent. An authentication failure against ACR, a rate limit from Docker Hub, and a network-level failure reaching a private registry all produce provisioning failures that look similar in the Azure portal ("Container failed to start"). The ContainerAppSystemLogs entries for each failure type differ in the Message field, but support engineers must know which patterns to look for to distinguish them. Image pull failures are also silent when the previous revision is still running — the new revision silently stays unprovisioned.
3. Customer symptom¶
"I deployed a new revision but it never became active" or "My Container App used to pull from Docker Hub but now it fails intermittently" or "I updated my ACR credential but the app still can't pull the image."
4. Hypothesis¶
- H1: When ACR authentication fails (wrong password, expired service principal, revoked managed identity role), the replica provisioning fails with a message in
ContainerAppSystemLogsthat includes "unauthorized" or "authentication required". The previous revision continues serving traffic if traffic splitting is configured; if there is no previous active revision, the app returns 503. - H2: Docker Hub rate limiting (429 Too Many Requests) produces a distinct error in
ContainerAppSystemLogscompared to an authentication failure (401). The rate limit error appears as a pull failure with "toomanyrequests" in the message. - H3: When pulling from a private registry over a Private Endpoint without proper DNS or network configuration, the pull fails with a network timeout, not an authentication error.
- H4: After an image pull failure, the previous revision continues serving traffic uninterrupted.
5. Environment¶
| Parameter | Value |
|---|---|
| Service | Azure Container Apps |
| SKU / Plan | Consumption |
| Region | Korea Central |
| Environment | env-batch-lab |
| App name | aca-diag-batch |
| Date tested | 2026-05-04 |
6. Variables¶
Experiment type: Reliability / Configuration
Controlled:
- Container App:
aca-diag-batchwith active revision--0000001serving traffic - Image registry: Microsoft Container Registry (MCR) — public, no credentials required
Observed:
- CLI error message when deploying with a non-existent image tag
- App HTTP response during and after failed revision deployment
- Revision state (active/inactive) after failed pull
Scenarios:
- S1: Deploy with valid image tag → success (baseline)
- S2: Deploy with non-existent image tag → pull failure, observe error message and traffic behavior
7. Instrumentation¶
az containerapp update --image <bad-tag>— triggers revision deployment and pull attemptcurlHTTP check against app URL during failed deploymentaz containerapp revision list— revision state and traffic weight after failure
8. Procedure¶
- Baseline: App running with
mcr.microsoft.com/azuredocs/containerapps-helloworld:latest. Confirm HTTP 200. - Attempt
az containerapp update --image mcr.microsoft.com/azuredocs/containerapps-helloworld:nonexistent-tag-12345. - Observe CLI error output.
- Immediately curl the app URL — verify existing revision still serves traffic.
- Check
az containerapp revision listfor active revision state and traffic weights.
9. Expected signal¶
- S2: CLI returns an error with "MANIFEST_UNKNOWN" or similar; the update command fails before committing; previous revision stays active and serving.
10. Results¶
S1 — Baseline (valid image)¶
```text App URL: https://aca-diag-batch.agreeablehill-e6bfb5a7.koreacentral.azurecontainerapps.io/ HTTP: 200 Active revision: aca-diag-batch--0000001 (replicas: 1, traffic: 70)
```text
S2 — Non-existent image tag¶
```bash $ az containerapp update -n aca-diag-batch -g rg-lab-aca-batch \ --image "mcr.microsoft.com/azuredocs/containerapps-helloworld:nonexistent-tag-12345"
```text
```text ERROR: Failed to provision revision for container app 'aca-diag-batch'. Error details: The following field(s) are either invalid or missing. Field 'template.containers.aca-diag-batch.image' is invalid with details: 'Invalid value: "mcr.microsoft.com/azuredocs/containerapps-helloworld:nonexistent-tag-12345": GET https:: MANIFEST_UNKNOWN: manifest tagged by "nonexistent-tag-12345" is not found; map[Tag:nonexistent-tag-12345]'
```text
App behavior during failed revision¶
```text HTTP after failed update: 200
Previous revision continued serving traffic uninterrupted¶
```text
Revision state after failed update¶
```text Name Active Traffic Healthy
aca-diag-batch--0000001 True 70 Healthy aca-diag-batch--0000002 True 0 Healthy aca-diag-batch--0000003 True 0 Healthy
```text No new revision was created. The bad image update was rejected at the provisioning layer before a new revision record was written.
11. Interpretation¶
- Observed: The CLI returns a synchronous error for a non-existent image tag — the error
MANIFEST_UNKNOWNis surfaced immediately during theaz containerapp updatecall. The platform validates the image tag before committing the revision. - Observed: The existing active revision (
--0000001) continued serving HTTP 200 throughout the failed update. H4 is confirmed — traffic is uninterrupted when a new revision fails to deploy. - Inferred: The
MANIFEST_UNKNOWNerror is specific to "tag not found on the registry." This is distinct from authentication failures (which would return "unauthorized" or "authentication required") and rate limit errors ("toomanyrequests"). - Inferred: The platform performs a registry manifest check during
az containerapp updateand rejects the request before creating a new revision record. No new revision appears inaz containerapp revision list. - Not Proven: Authentication failure (wrong ACR password) error message format was not tested in this experiment. H1 error text requires a separate test with invalid credentials.
12. What this proves¶
- A non-existent image tag is caught synchronously at the CLI level — no new revision is created. Observed.
- The error message
MANIFEST_UNKNOWN: manifest tagged by "..." is not foundis the specific format for a tag-not-found failure on MCR. Observed. - Existing active revisions continue serving traffic uninterrupted when a new revision fails to deploy. Observed (H4 confirmed).
- The previous revision's traffic weight and health state are unchanged after a failed new-revision deployment. Observed.
13. What this does NOT prove¶
- Authentication failure error message format (ACR wrong password → "unauthorized") was not captured. A separate test with invalid credentials is needed.
- Docker Hub rate limit error format ("toomanyrequests") was not reproduced. That requires a Docker Hub image under a free account with high pull volume.
- Private registry network failure error format was not tested.
- Behavior when pulling an image that exists at the registry but the Container App's managed identity lacks the
AcrPullrole was not tested.
14. Support takeaway¶
When a customer reports "I updated the image but the new revision never appeared":
- Check the CLI/portal error message during the update — if
MANIFEST_UNKNOWN, the image tag does not exist at the registry. Verify the tag withaz acr repository show-tagsordocker manifest inspect. - If the update appears to succeed but no new revision is active, check
az containerapp revision listand look for a revision inProvisioningorFailedstate. - Key error string patterns to identify pull failure type:
MANIFEST_UNKNOWN→ tag not found; check tag name spelling and registry sourceunauthorized/authentication required→ credential issue; rotate and redeploytoomanyrequests→ Docker Hub rate limit; switch to ACR mirror or use authenticated pulldial tcp: lookup ... no such host→ DNS resolution failure; check Private DNS Zone link- After any pull failure, the previous revision's traffic weight and health are preserved — the app stays up. A new revision must be explicitly deployed with a correct image to change the active revision.
15. Reproduction notes¶
```bash RG="rg-lab-aca-batch" APP="aca-diag-batch"
S2: Deploy with non-existent tag (will fail)¶
az containerapp update -n $APP -g $RG \ --image "mcr.microsoft.com/azuredocs/containerapps-helloworld:nonexistent-tag-99999"
Expected: ERROR with MANIFEST_UNKNOWN¶
Verify app still up¶
curl -s -o /dev/null -w "%{http_code}" \ "https://aca-diag-batch.agreeablehill-e6bfb5a7.koreacentral.azurecontainerapps.io/"
Expected: 200¶
Check revisions unchanged¶
az containerapp revision list -n $APP -g $RG \ --query "[].{name:name,active:properties.active,traffic:properties.trafficWeight}" -o table
``text
- Docker Hub rate limits apply per egress IP. The Container Apps environment's shared egress IP may be rate-limited across all apps if they all pull from Docker Hub.
- ACR managed identity pull requires theAcrPull` role on the registry assigned to the Container App's identity, not the environment.
- A failed new-revision pull does not deactivate the previous active revision; traffic continues on the old revision.