Blob HEAD and GET return 412 instead of 404 for a missing blob with If-Match
- Dominant language
- TypeScript
- Stars
- 2.3k
- Forks
- 393
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 36
Description
## Description
Azurite returns `412 ConditionNotMet` when `HEAD` or `GET` targets a missing blob with `If-Match` set to a valid ETag obtained from another blob. Azure Blob Storage returns `404 BlobNotFound` for the same requests.
This prevents clients and compatibility tests from distinguishing a missing blob from an existing blob whose ETag does not match.
## Reproduction
Tested with:
- `mcr.microsoft.com/azure-storage/azurite:3.37.0`
- Also reproduced with Azurite 3.35.0
- `x-ms-version: 2022-11-02`
- Raw Shared Key REST requests
Steps:
1. Create a container.
2. Create blob A and save the ETag returned by Azurite.
3. Choose a different blob name B that does not exist in the same container.
4. Send `HEAD` for blob B with `If-Match: `.
5. Send `GET` for blob B with the same `If-Match` value.
The ETag must be a valid value returned by the service. A synthetic malformed ETag is not an equivalent reproduction because Azure Storage can reject it as a failed condition.
## Actual behavior
| Service | HEAD missing blob | GET missing blob |
| --- | --- | --- |
| Azurite 3.37.0 | `412 ConditionNotMet` | `412 ConditionNotMet` |
| Azurite 3.35.0 | `412 ConditionNotMet` | `412 ConditionNotMet` |
Azurite 3.37.0 request IDs from one reproduction:
- HEAD: `5d0c1796-dce8-44a9-a8cc-d531185ac35b`
- GET: `c51e7848-072a-4405-9307-aaced86f9b70`
## Expected behavior
Match Azure Blob Storage and return `404 BlobNotFound` for both requests because blob B does not exist.
The same raw requests against the live Azure Blob Storage service returned:
| Service | HEAD missing blob | GET missing blob |
| --- | --- | --- |
| Azure Blob Storage | `404 BlobNotFound` | `404 BlobNotFound` |
Azure request IDs from the control reproduction:
- HEAD: `b7fcf34d-c01e-000d-26ff-35582f000000`
- GET: `067d7966-601e-0014-38ff-35d894000000`
## Impact
Clients that expose missing-target and conditional-mismatch results separately cannot run the same conditional read tests against Azurite and Azure Storage. A client-side existence check is not a suitable compatibility workaround because it adds another request and introduces a race.
AI assisted with the live-service comparison and drafting. The submitter directed the scope and conclusion.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the HEAD and GET requests against a missing blob using a valid ETag from another blob, then trace Azurite's conditional request handling for these operations. Add regression coverage for both methods and verify that each returns 404 BlobNotFound rather than 412 ConditionNotMet, while existing-blob mismatches remain covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, typescript
- Domain
- api, backend, cloud
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100