title: "The specified block list is invalid" while uploading blobs in parallel
body: <p>I've a (fairly large) Azure application that uploads (fairly large) files in parallel to Azure blob storage. </p>
  
  <p>In a few percent of uploads I get an exception:</p>
  
  <p><code>The specified block list is invalid.</code></p>
  
  <p><code>System.Net.WebException: The remote server returned an error: (400) Bad Request.</code></p>
  
  <p>This is when we run a fairly innocuous looking bit of code to upload a blob in parallel to Azure storage:</p>
  
  <pre><code>    public static void UploadBlobBlocksInParallel(this CloudBlockBlob blob, FileInfo file) 
      {
          blob.DeleteIfExists();
          blob.Properties.ContentType = file.GetContentType();
          blob.Metadata["Extension"] = file.Extension;
  
          byte[] data = File.ReadAllBytes(file.FullName);
  
          int numberOfBlocks = (data.Length / BlockLength) + 1;
          string[] blockIds = new string[numberOfBlocks];
  
          Parallel.For(
              0, 
              numberOfBlocks, 
              x =&gt;
          {
              string blockId = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
              int currentLength = Math.Min(BlockLength, data.Length - (x * BlockLength));
  
              using (var memStream = new MemoryStream(data, x * BlockLength, currentLength))
              {
                  var blockData = memStream.ToArray();
                  var md5Check = System.Security.Cryptography.MD5.Create();
                  var md5Hash = md5Check.ComputeHash(blockData, 0, blockData.Length);
  
                  blob.PutBlock(blockId, memStream, Convert.ToBase64String(md5Hash));
              }
  
              blockIds[x] = blockId;
          });
  
          byte[] fileHash  = _md5Check.ComputeHash(data, 0, data.Length);
          blob.Metadata["Checksum"] = BitConverter.ToString(fileHash).Replace("-", string.Empty);
          blob.Properties.ContentMD5 = Convert.ToBase64String(fileHash);
  
          data = null;
          blob.PutBlockList(blockIds);
          blob.SetMetadata();
          blob.SetProperties();
      }
  </code></pre>
  
  <p>All very mysterious; I'd think the algorithm we're using to calculate the block list should produce strings that are all the same length...</p>