We have identified an issue that would affect services using Windows Azure Tables whenever the percent character ‘%’ appears as part of the PartitionKey or RowKey.
The affected APIs are GET entity, Merge Entity, Update Entity, Delete Entity, Insert Or Merge Entity and Insert Or Replace Entity APIs. If any of these APIs are invoked with a PartitionKey or RowKey that contains the ‘%’ character, the user could erroneously receive a 404 Not Found or 400 Bad Request error code. In addition, in the case of upsert (Insert Or Merge Entity and Insert Or Replace APIs), the request might succeed but the stored string might not be what the user intended it to be.
Note that Insert Entity, Entity Group Transactions and Query Entities APIs are not affected since the PartitionKey and RowKey is not part of the URL path segment.
The Windows Azure Table Service is double decoding the URL path segment when processing a request which is resulting in an erroneous interpretation of the string whenever the ‘%’ character appears. Note that the query string portion of the URL is not affected by this issue nor is any URL that appears as part of the HTTP body. Therefore, any other property filters used in a query will be unaffected by this issue – only PartitionKey and RowKey are affected.
Here is an example of how this issue occurs: Inserting an entity with PartitionKey = “Metric%25” and RowKey = “Count” would succeed, since PartitionKey, RowKey and custom values are part of the request payload and not the URL path segment. Now, when you intend to retrieve this existing entity, the Get Entity HTTP URL will look like:
However due to the double decoding bug, the PartitionKey is getting interpreted as “Metric%” on the server side which is not what the user intended. In this case, a 404 Not Found is returned.
If you did not currently commit any entities where ‘%’ is used as part of the PartitionKey or RowKey we suggest that you consider the following:
Note: Do not double encode your PartitionKey and RowKey values as a workaround, since this would not be compatible with future Windows Azure Tables releases when a fix is applied on the server side.
In case you already have inserted entities where ‘%’ appears as part of the PartitionKey or RowKey, we suggest the following workarounds:
Consider the case where the user has already inserted an entity with PartitionKey = “Metric%25” and RowKey = “Count”. The following code shows how to use the Windows Azure Storage Client Library in order to retrieve and update that entity. The code uses the Entity Group Transaction workaround mentioned in the previous section. Note that both the Get Entity and Update Entity operations are performed as a batch operation.
// Creating a Table Service Context
TableServiceContext tableServiceContext = new TableServiceContext(tableClient.BaseUri.ToString(), tableClient.Credentials);
// Create a single point query
DataServiceQuery<MetricEntity> getEntityQuery = (DataServiceQuery<MetricEntity>)
from entity in tableServiceContext.CreateQuery<MetricEntity>(customersTableName)
where entity.PartitionKey == "Metric%25" && entity.RowKey == "Count"
// Create an entity group transaction with an inner Get Entity request
DataServiceResponse batchResponse = tableServiceContext.ExecuteBatch(getEntityQuery);
// There is only one response as part of this batch
QueryOperationResponse response = (QueryOperationResponse) batchResponse.First();
if (response.StatusCode == (int) HttpStatusCode.OK)
IEnumerator queryResponse = response.GetEnumerator();
// Read this single entity
MetricEntity singleEntity = (MetricEntity)queryResponse.Current;
// Updating the entity
singleEntity.MetricValue = 100;
// Make sure to save with the Batch option
As the issue discussed above is related to the service, the same behavior will exhibit when performing single entity operations using the Storage Client Library for Java. However, it is also possible to use Entity Group Transaction to work around this issue. The latest version that can be used to implement the proposed workaround can be found in here.
// Define a batch operation.
TableBatchOperation batchOperation = new TableBatchOperation();
// Retrieve the entity
batchOperation.retrieve("Metric%25", "Count", MetricEntity.class);
// Submit the operation to the table service.
For more on working with Tables via the Java Storage Client see: http://blogs.msdn.com/b/windowsazurestorage/archive/2012/03/05/windows-azure-storage-client-for-java-tables-deep-dive.aspx
We will be fixing this issue as part of a version change in a future release. We will update this post with the storage version that contains the fix.
We apologize for any inconvenience this may have caused.