Skip to content

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

Description

@Xuanwo

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: <etag-from-blob-A>.
  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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions