Azure / Azure/Azurite

Blob HEAD and GET return 412 instead of 404 for a missing blob with If-Match

Open
#2,751 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.