Storage data errors — 404, 409, 412, 416, 503 on Blob and ADLS Gen2
The errors a storage request gets after it is authorized — not found, already exists, being deleted, leases, conditional requests and ETags, archive tier, immutability, block limits, hierarchical-namespace conflicts between the Blob and Data Lake APIs, copy failures, server busy and timeouts — with the verbatim code and message from Microsoft's REST code tables, cause, check and fix.
markdownreferencev1TYA1-XKAPstage: operatetrust: officialservice: storageinterface: anyBlobNotFoundThe specified blob does not exist.ContainerNotFoundThe specified container does not exist.ContainerAlreadyExistsBlobAlreadyExistsContainerBeingDeletedThe specified container is being deleted.ResourceNotFoundLeaseIdMissingLeaseIdMismatchWithBlobOperationLeaseAlreadyPresentLeaseLostConditionNotMetThe condition specified in the conditional header(s) was not met for a write operation.412 Precondition Failed ETagBlobArchivedBlobBeingRehydratedThis operation is not permitted on an archived blob.BlobImmutableDueToPolicyBlobImmutableDueToLegalHoldBlockCountExceedsLimitInvalidBlockListBlobOperationNotSupportedInvalidFlushOperationPathNotFoundFilesystemNotFoundDirectoryNotEmptyPathConflictCannotVerifyCopySourceCopyAcrossAccountsNotSupportedPendingCopyOperationServerBusyOperations per second is over the account limit.Egress is over the account limit.OperationTimedOutMd5MismatchInvalidRangeRequestBodyTooLargeInvalidResourceNameOutOfRangeInputstorage 503 retry
Storage data errors — 404, 409, 412, 416, 503
These come back once the request is authorized (reference/storage/access-errors.md covers 401 and 403). Messages are the REST tables' wording; the service appends RequestId: and Time: lines. Status 409 errors are usually state, not bugs: read the code before retrying.
Not found, exists, being deleted
| Code / message | Cause → fix | Check |
|---|---|---|
404 ContainerNotFound The specified container does not exist. | Wrong container name (lowercase, 3–63 characters), wrong account, or never created. Create it with createIfNotExists() | az storage container exists -n <c> --account-name <acct> --auth-mode login |
404 BlobNotFound The specified blob does not exist. | Name is case-sensitive and includes the virtual "folder" path; or the blob was deleted (soft delete may still hold it) | az storage blob list -c <c> --prefix <path> --account-name <acct> --auth-mode login --include d |
404 ResourceNotFound The specified resource doesn't exist. | Generic form, also from Queue and Table | Name and endpoint (blob. vs dfs. vs queue.) |
409 ContainerAlreadyExists / BlobAlreadyExists | Create without overwrite on an existing name. Use createIfNotExists(), or upload with overwrite | Expected on reruns: treat as success when idempotent |
409 ContainerBeingDeleted The specified container is being deleted. | A container of that name was just deleted; deletion takes time. Retry later or use a new name | Retry with backoff; don't delete and re-create in tests |
404 FilesystemNotFound / PathNotFound (Data Lake) | Same as the Blob codes on the dfs endpoint | az storage fs exists, az storage fs file exists |
Leases and conditional requests
| Code / message | Cause → fix | Check |
|---|---|---|
412 LeaseIdMissing There is currently a lease on the blob/container and no lease ID was specified in the request. | Another writer (or a crashed one) holds a lease. Pass the lease ID, wait for it to expire, or break it deliberately | az storage blob show … --query properties.lease |
412 LeaseIdMismatchWithBlobOperation / 409 LeaseAlreadyPresent | Wrong lease ID, or acquiring a lease someone holds | Same |
412 LeaseLost A lease ID was specified, but the lease for the blob/container has expired. | Lease ran out (15–60 s unless infinite) during a long write: renew it | Lease duration vs the work's length |
412 ConditionNotMet The condition specified in the conditional header(s) was not met for a write operation. | Optimistic concurrency working as designed: the ETag (If-Match) changed because someone else wrote. Re-read, merge, retry | Compare the ETag you hold with az storage blob show … --query properties.etag |
304 ConditionNotMet on a read | If-None-Match matched: your cached copy is current | Not an error |
Tiers, immutability and limits
| Code / message | Cause → fix | Check |
|---|---|---|
409 BlobArchived This operation is not permitted on an archived blob. | Archive is offline. Rehydrate to hot, cool or cold (copy or set tier); it can take up to 15 hours | properties.blobTier, properties.archiveStatus |
409 BlobBeingRehydrated | Rehydration in progress | archiveStatus |
409 BlobImmutableDueToPolicy / BlobImmutableDueToLegalHold | Time-based retention or a legal hold: the blob can't change or be deleted until it ends | az storage container immutability-policy show / az storage container legal-hold show |
409 BlockCountExceedsLimit | More than 50,000 committed or 100,000 uncommitted blocks. Use larger blocks (the SDK's uploadFile/uploadStream choose sizes) | Block size × count |
400 InvalidBlockList / InvalidBlockId | Block IDs not Base64, or of differing lengths within one blob | Let the SDK stage blocks |
416 InvalidRange The range specified is invalid for the current size of the resource. | Ranged read past the end | Blob contentLength |
413 RequestBodyTooLarge | A single Put exceeds the operation's maximum: use block upload | SDK upload helpers |
400 Md5Mismatch | Content changed in transit, or the MD5 was computed over different bytes | Recompute over the exact upload buffer |
Hierarchical namespace (ADLS Gen2)
| Code / message | Cause → fix | Check |
|---|---|---|
409 BlobOperationNotSupported (Put Block / Put Block List on a file created by Path - Create) | Blob and Data Lake APIs can't both write one file. Overwrite with Put Blob, or write with the Data Lake client | reference/storage/adls-gen2.md |
409 InvalidFlushOperation The resource was created or modified by the Blob Service API and cannot be written to by the Data Lake Storage Service API. | The reverse case | Same |
409 DirectoryNotEmpty The recursive query parameter value must be true to delete a non-empty directory. | Delete with recursive: true. Blob API Delete only removes empty directories | — |
409 PathConflict / PathAlreadyExists | A file exists where a directory is expected, or the reverse | az storage fs file show |
| Page-blob, append-seal or incremental-copy calls fail | Not supported on hierarchical-namespace accounts | Use a separate account |
Copy
| Code / message | Cause → fix | Check |
|---|---|---|
500 CannotVerifyCopySource Could not verify the copy source within the specified time. | The destination service couldn't read the source: source firewall, private endpoint in another VNet, or the source SAS/role doesn't allow read | Can the destination account reach and read the source URL? |
400 CopyAcrossAccountsNotSupported | The operation (for example some incremental copies) requires one account | Use Copy Blob from URL with a SAS or Entra source auth |
409 PendingCopyOperation / NoPendingCopyOperation | Starting a copy while one runs, or aborting none | properties.copy.status |
Server busy and timeouts
| Code / message | Cause → fix | Check |
|---|---|---|
503 ServerBusy Operations per second is over the account limit. / Ingress is over the account limit. / Egress is over the account limit. / The server is currently unable to receive requests. Please retry your request. | Account scalability target reached. Retry with exponential backoff (the SDKs retry by default: 4 tries, 4 s base, 120 s cap); spread load over prefixes or accounts; request higher limits through Support. The limit values are adjustable and not typed here | Azure Monitor metric Transactions split by ResponseType; scalability targets page |
500 OperationTimedOut The operation could not be completed within the permitted time. The operation may or may not have succeeded on the server side. Please query the server state before retrying the operation. | Check state before retrying a non-idempotent write | Read the blob's properties first |
500 InternalError | Transient: retry with backoff | — |
400 InvalidResourceName / OutOfRangeInput | Names: containers lowercase letters, numbers and hyphens, 3–63; blob names up to 1,024 characters | Name rules on Learn's naming page |