Azure Blob: "Condition specified using conditional HTTP headers not fulfilled"

I got this exception when I run the application. This also happens in the real Azure firewall repository.

I caught with Fiddler a request that creates this problem:

GET http://127.0.0.1:10000/devstoreaccount1/ebb413ed-fdb5-49f2-a5ac-74faa7e2d3bf/8844c3ec-9e4b-43ec-88b2-58eddf65fc0a/perro?timeout=90 HTTP/1.1 x-ms-version: 2009-09-19 User-Agent: WA-Storage/6.0.6002.18006 x-ms-range: bytes=0-524304 If-Match: 0x8CDA190BD304DD0 x-ms-date: Wed, 23 Feb 2011 16:49:18 GMT Authorization: SharedKey devstoreaccount1:5j3IScY9UJLN3o1ICWKwVEazO4/IDJG796sdZKqHlR4= Host: 127.0.0.1:10000 

And this is the answer:

 HTTP/1.1 412 The condition specified using HTTP conditional header(s) is not met. Content-Length: 252 Content-Type: application/xml Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: fbff9d15-65c8-4f21-9088-c95e4496c62c x-ms-version: 2009-09-19 Date: Wed, 23 Feb 2011 16:49:18 GMT <?xml version="1.0" encoding="utf-8"?><Error><Code>ConditionNotMet</Code><Message>The condition specified using HTTP conditional header(s) is not met. RequestId:fbff9d15-65c8-4f21-9088-c95e4496c62c Time:2011-02-23T16:49:18.8790478Z</Message></Error> 

This happens when I use Stream extracted from this line:

 blob.OpenRead(); 

Why are ETAG minds in a read operation? How can I avoid this problem?

This happens every time I run several parallel tasks that do things on blob storage.

If I use:

 blob.OpenRead(new BlobRequestOptions() { AccessCondition = AccessCondition.IfMatch("*") }); 

I got this exception without an internal one (before it had a WebException with details), or a failure line in Fiddler:

 Microsoft.WindowsAzure.StorageClient.StorageClientException was unhandled Message=The conditionals specified for this operation did not match server. Source=mscorlib StackTrace: Server stack trace: at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.get_Result() at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.ExecuteAndWait() at Microsoft.WindowsAzure.StorageClient.TaskImplHelper.ExecuteImpl[T](Func`2 impl) at Microsoft.WindowsAzure.StorageClient.BlobReadStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.IO.BinaryReader.ReadBytes(Int32 count) at System.Runtime.Serialization.Formatters.Binary.SerializationHeaderRecord.Read(__BinaryParser input) at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadSerializationHeaderRecord() at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run() at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) ........... 

Thanks in advance.

+8
blob azure azure-storage azure-storage-blobs
source share
3 answers

Buffer ... mistery decided!

Well, when you do CloudBlob.OpenRead() , the client library does two CloudBlob.OpenRead() :

First get a list of blob blocks:

 GET /devstoreaccount1/etagtest/test2.txt?comp=blocklist&blocklisttype=Committed&timeout=90 HTTP/1.1 x-ms-version: 2009-09-19 User-Agent: WA-Storage/6.0.6002.18006 x-ms-date: Wed, 23 Feb 2011 22:21:01 GMT Authorization: SharedKey devstoreaccount1:SPOBe/IUrZJvoPXnAdD/Twnppvu37+qrUbHnaBHJY24= Host: 127.0.0.1:10000 HTTP/1.1 200 OK Transfer-Encoding: chunked Content-Type: application/xml Last-Modified: Wed, 23 Feb 2011 22:20:33 GMT ETag: 0x8CDA1BF0593B660 Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: ecffddf2-137f-403c-9595-c8fc2847c9d0 x-ms-version: 2009-09-19 x-ms-blob-content-length: 4 Date: Wed, 23 Feb 2011 22:21:02 GMT 

Attention to ETag in the answer.

Secondly, I think you should start extracting it, and now attention to ETag in the request:

 GET /devstoreaccount1/etagtest/test2.txt?timeout=90 HTTP/1.1 x-ms-version: 2009-09-19 User-Agent: WA-Storage/6.0.6002.18006 x-ms-range: bytes=0-525311 If-Match: 0x8CDA1BF0593B660 x-ms-date: Wed, 23 Feb 2011 22:21:02 GMT Authorization: SharedKey devstoreaccount1:WXzXRv5e9+p0SzlHUAd7iv7jRHXvf+27t9tO4nrhY5Q= Host: 127.0.0.1:10000 HTTP/1.1 206 Partial Content Content-Length: 4 Content-Type: text/plain Content-Range: bytes 0-3/4 Last-Modified: Wed, 23 Feb 2011 22:20:33 GMT ETag: 0x8CDA1BF0593B660 Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: db1e221d-fc61-4837-a255-28b1547cb5d7 x-ms-version: 2009-09-19 x-ms-lease-status: unlocked x-ms-blob-type: BlockBlob Date: Wed, 23 Feb 2011 22:21:02 GMT 

What happens if another WebRole does something in blob between calls? YES race condition .

Solution: use CloudBlob.DownloadToStream() , this method only calls one call:

 GET /devstoreaccount1/etagtestxx/test2.txt?timeout=90 HTTP/1.1 x-ms-version: 2009-09-19 User-Agent: WA-Storage/6.0.6002.18006 x-ms-date: Wed, 23 Feb 2011 22:34:02 GMT Authorization: SharedKey devstoreaccount1:VjXIO2kbjCIP4UeiXPtxDxmFLeoYAKOqiRv4SV3bZno= Host: 127.0.0.1:10000 HTTP/1.1 200 OK Content-Length: 4 Content-Type: text/plain Last-Modified: Wed, 23 Feb 2011 22:33:47 GMT ETag: 0x8CDA1C0DEB562D0 Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: 183a05bb-ea47-4811-8768-6a62195cdb64 x-ms-version: 2009-09-19 x-ms-lease-status: unlocked x-ms-blob-type: BlockBlob Date: Wed, 23 Feb 2011 22:34:02 GMT 

I'll put it into practice tomorrow morning at work and see what happens.

+6
source

One thing that comes to mind is that ETag's

 If-Match: 0x8CDA190BD304DD0 

is incorrect; the actual (strong) stage is always in double quotes.

I don't know if this has anything to do with your problem.

+1
source

You can still use OpenRead, you need to pass an OperationContext instance as shown below:

 // cloudBlob instance of CloudPageBlob OperationContext context = new OperationContext(); context.SendingRequest += (sender, e) => { e.Request.Headers["if-match"] = "*"; }; using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { cloudBlob.StreamMinimumReadSizeInBytes = 16385; var result = cloudBlob.BeginOpenRead(null, null, context, ar => waitHandle.Set(), null); waitHandle.WaitOne(); using (Stream blobStream = vhd.EndOpenRead(result)) { var k = blobStream.ReadByte(); } } 
+1
source

All Articles