Azure Error Guide: 'ResourceNotFound' The Requested Resource Was Not Found
Fix the Azure ResourceNotFound ARM error: wrong subscription, deleted resources, name casing, api-version mismatches, and propagation delays.
- #azure
- #troubleshooting
- #errors
- #resource-manager
Exact Error Message
When Azure Resource Manager (ARM) cannot locate a resource you reference, it returns a ResourceNotFound error. The exact text looks like this:
(ResourceNotFound) The Resource 'Microsoft.Compute/virtualMachines/web-01' under resource group 'rg-prod' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix
Code: ResourceNotFound
Message: The Resource 'Microsoft.Compute/virtualMachines/web-01' under resource group 'rg-prod' was not found.
A closely related variant fires when the resource group itself is missing:
(ResourceGroupNotFound) Resource group 'rg-prod' could not be found.
Code: ResourceGroupNotFound
You will see these surfaced through the Azure CLI, ARM/Bicep deployments, Terraform’s azurerm provider, the REST API (as an HTTP 404), and the Azure portal.
What the Error Means
ResourceNotFound is ARM telling you, very literally, that the resource ID you asked it to operate on does not exist in the scope you targeted. ARM resolves every request against a fully qualified resource ID of the form:
/subscriptions/{subId}/resourceGroups/{rg}/providers/{provider}/{type}/{name}
If any segment in that path is wrong, or the resource at the end of the path has been deleted, ARM returns a 404. The error is scoped: it is reported relative to the subscription and resource group ARM was searching in. This is the key insight. Most “the resource clearly exists” cases are really “the resource exists, but not in the place ARM looked.” Your CLI context, the active subscription, or a mistyped resource group quietly redirected the lookup.
Common Causes
- Wrong active subscription or context. The resource lives in a different subscription than your current CLI/portal context. This is the single most common cause.
- Resource was deleted or renamed. Someone removed the VM, a teardown pipeline ran, or it was recreated with a new name.
- Wrong resource group. The name is correct but you are pointing at the wrong resource group, or the RG was deleted entirely (yielding
ResourceGroupNotFound). - Casing differences in the name. While resource names are generally case-insensitive for matching, IDs constructed by hand or passed through scripts can drift, and some downstream tools and tags are case-sensitive.
- Wrong api-version. A resource type or property may not exist under the api-version you specified, so the provider reports the resource as not found.
- Eventual-consistency propagation. Immediately after creating a resource, ARM’s read replicas may not yet reflect it. A follow-up read in the same pipeline can 404 for a few seconds.
- Parent resource missing. Child resources (subnets, NIC IP configs, blob containers) cannot be found if their parent (VNet, NIC, storage account) does not exist or was named incorrectly.
How to Reproduce the Error
The fastest way to see it is to query a resource in the wrong subscription. Set your context to a subscription that does not contain the VM, then read it:
# Active context points at the "sandbox" subscription
az account set --subscription "sandbox"
# But web-01 actually lives in the "prod" subscription
az vm show --resource-group rg-prod --name web-01
This returns:
(ResourceNotFound) The Resource 'Microsoft.Compute/virtualMachines/web-01' under resource group 'rg-prod' was not found.
You can reproduce the casing/typo variant by referencing a name that does not exactly match (web01 instead of web-01), or the propagation variant by reading a resource in a pipeline step that runs milliseconds after creation.
Diagnostic Commands
Start with read-only commands to confirm where ARM is looking and what actually exists. None of these change state.
# 1. Confirm which subscription is active right now
az account show --output table
# 2. List every subscription you can see, and find the right one
az account list --output table
# 3. List all resources in the resource group you expect
az resource list --resource-group rg-prod --output table
# 4. Show a resource by its full ID (bypasses RG/name guessing)
az resource show --ids "/subscriptions/<subId>/resourceGroups/rg-prod/providers/Microsoft.Compute/virtualMachines/web-01"
# 5. Confirm the resource group exists at all
az group show --name rg-prod --output table
# 6. Search across the RG by name fragment, case-insensitive, to catch typos
az resource list --resource-group rg-prod \
--query "[?contains(to_string(name), 'web')].{name:name, type:type}" \
--output table
# 7. Read the VM specifically once you believe context is correct
az vm show --resource-group rg-prod --name web-01 --output table
If command 1 shows the wrong subscription, you have found your problem before reading anything else.
Step-by-Step Resolution
1. Set the correct subscription. Identify the subscription that owns the resource, then make it active:
az account set --subscription "prod-subscription-id-or-name"
az account show --output table # verify it stuck
2. Verify the resource group exists and is spelled correctly.
az group show --name rg-prod --output table
If this returns ResourceGroupNotFound, the RG is the issue, not the resource. Check az group list --output table for the correct name.
3. List resources to confirm the exact name. Names drift over time. List what is actually present rather than trusting the value in your script:
az resource list --resource-group rg-prod --output table
4. Check the activity log for a recent delete. If the resource is genuinely gone, the activity log tells you who removed it and when. This is read-only:
az monitor activity-log list \
--resource-group rg-prod \
--offset 7d \
--query "[?contains(operationName.value, 'delete')].{op:operationName.value, status:status.value, time:eventTimestamp, caller:caller}" \
--output table
If you see a delete event, the fix is to recreate the resource (via your IaC pipeline, ideally) rather than to keep querying it.
5. Correct casing and api-version. When constructing IDs by hand or in templates, match the canonical name exactly and pin a supported api-version. List the versions a provider supports:
az provider show --namespace Microsoft.Compute \
--query "resourceTypes[?resourceType=='virtualMachines'].apiVersions[]" \
--output table
Use one of the returned versions in your ARM/Bicep/REST call.
6. Wait for propagation. If the resource was created moments ago in the same pipeline, add a short retry-with-backoff before the dependent read. A few seconds is usually enough; ARM templates handle this automatically via dependsOn, so prefer expressing dependencies declaratively instead of racing.
Prevention and Best Practices
- Pin subscription context explicitly in every script and pipeline with
az account set(or theARM_SUBSCRIPTION_IDenv var / provider block in Terraform). Never rely on the ambient default. - Reference resources by full resource ID rather than RG + name pairs where possible. IDs are unambiguous and survive context switches.
- Express dependencies declaratively. In ARM/Bicep use
dependsOn; in Terraform let implicit references build the graph. This eliminates propagation 404s. - Pin api-versions in templates and REST calls so a provider change does not silently break lookups.
- Add retry-with-backoff to post-create reads in custom automation.
- Protect critical resources with delete locks (
CanNotDelete) and tag ownership so accidental teardown is visible in the activity log.
For a broader workflow on diagnosing failed deployments, see our Azure troubleshooting guide.
Related Errors
- ResourceGroupNotFound — the resource group itself does not exist in the active subscription. Verify with
az group show. - NotFound (404) — the generic REST-layer equivalent returned by the ARM API and SDKs; same root causes.
- SubscriptionNotFound — the subscription ID in the request is invalid or not visible to your identity; check
az account list. - ParentResourceNotFound — a child resource (subnet, NIC config, container) was requested but its parent does not exist; create or correct the parent first.
- LinkedAuthorizationFailed — you reference a resource in another scope that your identity cannot read, which can surface as a not-found-style failure; grant read access on the linked resource.
Frequently Asked Questions
Q: The resource is clearly visible in the portal, so why does the CLI say it is not found?
A: Almost always a subscription-context mismatch. The portal may have a different subscription selected than your CLI session. Run az account show and compare it to the subscription shown in the portal’s resource overview, then az account set accordingly.
Q: Is ResourceNotFound ever transient?
A: Yes. Immediately after creation, ARM’s read replicas may not reflect the new resource for a few seconds. If a read 404s only in fast pipelines and succeeds on retry, it is propagation latency, not a real absence. Add a short backoff or declare an explicit dependency.
Q: Does resource name casing matter?
A: ARM matching is generally case-insensitive, but resource IDs you build by hand, tags, and some downstream tools are case-sensitive. Always copy the canonical name from az resource list rather than retyping it.
Q: How do I tell whether the resource was deleted versus never existed?
A: Query the activity log with az monitor activity-log list filtered on delete operations. A delete event names the caller and timestamp; no event over the resource’s expected lifetime suggests it was never created in that scope.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.