Avoiding Accidental Function Name Collisions
This week, I was working with Azure functions and had a very frustrating issue that I spent multiple days trying to get to the bottom of. This ended up being a reasonably straightforward issue with name collisions. Still, it wasn’t obvious and took a lot of digging to get to the bottom of, so I wanted to provide some details here in case anyone else hits the same problem.
The Problem
I was working with an Azure function that had been running for some time, but I needed to make some changes to the code. I also needed to rename the function, as its purpose had changed, and the current name didn’t fit. I was using infrastructure as code to deploy the functions, so to keep things simple, I had it destroy the old function and create a new one with the new name to avoid any issues with trying to rename things.
All worked fine when I deployed the function to a test environment from scratch (so no existing function). However, when I deployed it to another environment where it did need to delete the old function and create the new one, I hit a problem where the new function wouldn’t start. The function resource got deployed, but the actual function code wouldn’t start, and the portal showed the function as unhealthy. Looking at the logs, it gave some very vague errors:
Failed to start a new language worker for runtime: dotnet-isolated
and
A Task Was Cancelled
No amount of restarts or changes to configuration information made any difference, or generated any additional useful log data.
The Cause
With the help of MS support, we got to the bottom of the problem, and it was all down to the function’s name. The function had a relatively long name, greater than 32 characters (this will be important in a minute), and the names of the old and new functions were pretty similar, for example orgprojectregion-prefix001-createclientqueue
vs orgprojectregion-prefix001-createclientresources
.
The issue is that when the function starts, it uses an Azure storage account (that you specify, called webjobstorage) to store some metadata about triggers, etc. It creates a container for each function, but the container names are limited to 32 chars. The function name is used for the folder name, but if the function name is longer than 32 chars, it truncates it. I bet you can see what is coming now. The old and new function names, when truncated to 32 chars, are exactly the same. When the old function was destroyed, it didn’t clean up the folder in storage, so the new one couldn’t create one with the same name, and so it couldn’t start.
The function diagnostic logs didn’t show anything, but I did find later that if you looked in the “Diagnose and Solve Problems” tab and you knew to look at the Function Host Name Collision Check
page, it did mention that the function name was longer than 32 chars, and so could cause a problem.
The Solution
We have a couple of options to fix this issue. The first is to change the function name to be less than 32 chars, or at least different in the first 32 chars. This was challenging to do, so I went with a second option. You can set an app configuration value to set a Host ID for the function, which will be used in the storage to create the container name. To do this, set the AzureFunctionsWebHost__hostid
in the function configuration to the value you want to use for naming this.