question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Inconsistent ETag results in Storage Blob SDK GetPropertiesAsync and GetBlobsAsync and ETag documentation issue

See original GitHub issue

Library name and version

Azure.Storage.Blobs 12.13.0

Describe the bug

Hi Azure SDK Team.

I noticed some inconsistent ETag documentation and corresponding inconsistent behavior of ETag usage in at least two Azure Blob Storage APIs. I initially thought it would be two issues, but I think they are so related enough to be included in this one. Hope that is fine for you and does not produce any tracking issues.

Let me start with the documentation of the ToString method in the official documentation: https://docs.microsoft.com/de-de/dotnet/api/azure.etag.tostring?view=azure-dotnet#azure-etag-tostring(system-string) The following example is provided:

ETag tag = ETag.Parse("\"sometag\"");
Console.WriteLine(tag.ToString("G"));
// Displays: sometag
Console.WriteLine(tag.ToString("H"));
// Displays: "sometag"

This example cannot be used by external code, because the Parse method is internal. If I now use similar code, but initialize the Etag with the constructor that is public, the results will be wrong:

ETag tag = new ETag("\"sometag\"");
Console.WriteLine(tag.ToString("G"));
// Displays: "sometag"
Console.WriteLine(tag.ToString("H"));
// Displays: "sometag"

The results are wrong because the Parse method does trim the quotes during initialization, the constructor does not. For anyone using the API from the outside, this behavior is not obvious and lead to bugs in our code and possibly the inconsistent behavior of the two sdk methods provided in the reproduction steps.

Expected behavior

It would be a good thing to either make the ETag.Parse method publicly available, change the documentation to be more clear about quote behavior, or have the constructor behave the same way as the method.

I guess making the constructor behavior similiar could also immediately resolve the problem with creation of ETags, but is considerably more breaking.

Also, BlobClient.GetPropertiesAsync and BlobContainerClient.GetBlobsAsync should produce a consistent behavior of ETag formats.

Actual behavior

ETag.Parse is not public, and using the constructor results in a different behavior than stated in the documentation

BlobClient.GetPropertiesAsync and BlobContainerClient.GetBlobsAsync property results produce different ETag formats for the same Blob when formatted with ToString.

I noticed this behavior after updating from 12.10.0 to 12.13.0, which broke quite a few of our tests that assert on the ETags. This would have resulted in wrong ETag comparison behavior if it had slipped into production.

We currently work around it by always trimming all outer quotes from ETags whenever we load them from blob storage. This solution only works as long as we do not use Weak ETags.

Reproduction Steps

The two different ways of creating an ETag probably lead to the following inconsistent behavior of Storage SDK Methods BlobClient.GetPropertiesAsync and BlobContainerClient.GetBlobsAsync. If you fetch a Blob’s metadata using these two different approaches:

// fetching metadata for the single blob
props1 = await blobClient.GetPropertiesAsync(conditions: null, cancellationToken);
var etag1 = props1.ETag.ToString("G"); // produces "\"0xabcd1234\""

// fetching metadata for the blob as part of a batch
var blobs = _blobContainerClient.GetBlobsAsync(
            prefix: blobPrefix,
            traits: BlobTraits.Metadata,
            cancellationToken: cancellationToken);

await foreach (var blob in blobs.WithCancellation(cancellationToken))
{
     var etag2 = blob.Properties.ETag!.Value.ToString("G") // produces "0xabcd1234"
}

The blob ETag format is different, and a comparison of the two ETags ToString Calls would result in non-comparable data.

Environment

  • .NET 6.0.7 on Windows
  • IDE: VS Prof. 17.2.5

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
amnguyecommented, Sep 15, 2022

Unfortunately we would have to wait till something like version 13+ of the SDK (as of now we’re only doing v12.XX releases which do not allow breaking changes). We will consider this issue in the future, though we also have to consider the customers who would also be upset by the difference in the change, but that’s obviously up for future discussion.

We will look to updating the documentation for how the ETag value will come back with the quotations or not since this is a common issue.

0reactions
Schmagacommented, Sep 15, 2022

Thank you, sorry that my initial research did not find the above mentioned issue. But even if it is a breaking change, wouldn’t it be possible to update the behavior in a future major release, with deprecation or other notices up front? Or at least update the documentation to mention this flaw. The way it is now is very error-prone to use.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to ignore ETag checking and fix this error
Thinking it would ignore checking for matching ETag values. But this does not work. Using Azure.Storage.Blobs package.
Read more >
How to ignore ETag checking
My application reads blob content from Azure blob storage. The Blob content file is being changed by another program at the same time...
Read more >
Untitled
Etag blob What is purpose of ETag in ITableEntity - Stack Overflow ... NET [BUG] Inconsistent ETag results in Storage Blob SDK Can...
Read more >
Tip 88 - What's the purpose of ETag in Azure Storage Table?
An ETag property is used for optimistic concurrency during updates. It is not a timestamp as there is another property called TimeStamp that ......
Read more >
apache_beam.io.azure.blobstorageio - Apache Beam®
Source code for apache_beam.io.azure.blobstorageio. # # Licensed to the Apache Software Foundation (ASF) under one or more ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found