Nasty errors in Azurite Azure Blob Storage emulator

The context: local development of with Azurite Azure Blob Storage emulator

In order to simplify development for Azure Storage, Microsoft has created Azurite, an open-source Azure Storage API compatible server (emulator). It is a great tool for local development, as it allows you to run a local instance of Azure Storage services on your machine. This way, you can develop and test your applications without the need to connect to the cloud.

For example, you can use Azurite to test your application’s interaction with Azure Blob Storage. You can run Azurite on your local machine and then connect to it using the Azure Storage SDK. This way, you can test your application’s behavior without having to connect to the cloud. Tool is quite functional - it supports emulation of blobs, queues, and tables.

In my case I was using Azure Storage table service for counting likes and updating likes counter for this blog site. I was using Azurite to test the functionality locally. I am using Azure Blog inside my Azure Functions. Here is the code that works with table service:


  async private Task<int> UpdateLikes(string pagePath)
  {
      TableEntity? entity = null;
      var client = new TableClient(connectionString, TABLE_NAME);

      var entityResponse = await client.GetEntityIfExistsAsync<TableEntity>(partitionKey, pagePath);

      if (entityResponse.HasValue)
      {
          entity = entityResponse.Value;
          entity["Likes"] = (int)entity["Likes"] + 1;
      }
      else
      {
          entity = new TableEntity(partitionKey, pagePath)
          {
              ["Likes"] = 1
          };
      }

      await client.UpsertEntityAsync(entity, TableUpdateMode.Replace);

      return (int)entity["Likes"];
  }

In the code above, I am sending pagePath from the client javascript to Azure Function based API, and subsequently updating the likes counter in the table storage. During development everything was working fine, but then I started to get errors like this:


[2024-03-30T22:06:02.234Z] Function 'helpers', Invocation id '9dca5254-5c5f-4ea8-8fe3-7d1a5d54c9f4': An exception was thrown by the invocation.
[2024-03-30T22:06:02.235Z] Result: Function 'helpers', Invocation id '9dca5254-5c5f-4ea8-8fe3-7d1a5d54c9f4': An exception was thrown by the invocation.    
Exception: System.AggregateException: One or more errors occurred. (Service request failed.
[2024-03-30T22:06:02.236Z] Status: 500 (Internal Server Error)
[2024-03-30T22:06:02.237Z]
[2024-03-30T22:06:02.238Z] Headers:
[2024-03-30T22:06:02.239Z] Server: Azurite-Table/3.29.0
[2024-03-30T22:06:02.240Z] Date: Sat, 30 Mar 2024 22:06:02 GMT
[2024-03-30T22:06:02.241Z] Connection: keep-alive
[2024-03-30T22:06:02.242Z] Keep-Alive: REDACTED
[2024-03-30T22:06:02.243Z] Content-Length: 0
[2024-03-30T22:06:02.244Z] )
[2024-03-30T22:06:02.245Z]  ---> Azure.RequestFailedException: Service request failed.
[2024-03-30T22:06:02.246Z] Status: 500 (Internal Server Error)
[2024-03-30T22:06:02.247Z]
[2024-03-30T22:06:02.247Z] Headers:
[2024-03-30T22:06:02.248Z] Server: Azurite-Table/3.29.0
[2024-03-30T22:06:02.249Z] Date: Sat, 30 Mar 2024 22:06:02 GMT
[2024-03-30T22:06:02.250Z] Connection: keep-alive
[2024-03-30T22:06:02.251Z] Keep-Alive: REDACTED
[2024-03-30T22:06:02.252Z] Content-Length: 0
[2024-03-30T22:06:02.253Z]
[2024-03-30T22:06:02.254Z]    at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)
[2024-03-30T22:06:02.255Z]    at Azure.Data.Tables.TableRestClient.QueryEntityWithPartitionAndRowKeyAsync(String table, String partitionKey, String rowKey, Nullable`1 timeout, String format, String select, String filter, RequestContext context)
[2024-03-30T22:06:02.255Z]    at Azure.Data.Tables.TableClient.GetEntityInternalAsync[T](Boolean async, String partitionKey, String rowKey, Boolean noThrow, IEnumerable`1 select, CancellationToken cancellationToken)
[2024-03-30T22:06:02.256Z]    at Azure.Data.Tables.TableClient.GetEntityIfExistsAsync[T](String partitionKey, String rowKey, IEnumerable`1 select, CancellationToken cancellationToken)

After spending several hours trying to figure out what is wrong, I found out that the problem was with Azurite. The error message is not very helpful, but it seems that Azurite has some issues with handling row keys, when querying the table. I found out that the problem was with the row key that I was using for the table entity. I was using the pagePath as the row key, and it seems that Azurite has some issues with handling special characters in the row key. In my case value of pagePath was something like /blog/2024/03/19/nasty-errors, and it seems that the / character may cause issues with Azurite.

Solving the issue

Exact solution for issue that you encounter may be different, but here are some steps that you can take to troubleshoot the issue:

Escaping special characters in the row key

In my case I used UrlEncode method. Following code fixed the issue:


  string _pagePath =System.Net.WebUtility.UrlEncode(_likeRequest.Path);
  _logger.LogInformation($"Page path: {_pagePath}");

  int likes = await UpdateLikes(_pagePath);

Clean Azurite data

You can try to clean the Azurite data. You can do this by deleting the Azurite data folder. By default, Azurite stores its data in the C:\Azurite folder. You can change this folder in the Azurite settings. Same setting is available in Visual Studio Code when you run Azurite from there.

Use Azure Storage Explorer to add/edit data

You can doublecheck, if you can create table or data that you need with names and parameters that you need using Azure Storage Explorer. Azure Storage Explorer worked flawlessly for me, and I was able to create tables and add data without any issues.

View Azurite logs

And of course debug logs. Azurite allows to configure debug logs and they are very detailed. This is how I found cause of my issue. The specific problem was that Azurite was not able to distinguish table name from row key value as both are embedded in request URL.

That’s it. Happy coding!