Thursday, 15 March 2018

Azure Functions: Exception while executing function...connection string is missing or empty

I've recently started to play with Azure Functions trying them in Visual Studio with C# and in Visual Studio Code with JavaScript.

I've focused on the Http triggers specifically basic CRUD  interactions with Azure Table storage which will become a future series of blog posts.

My first attempt in C# went fairly smoothly, created a function then hit run and have Visual Studio handle starting the functions runtime which I then executed via Postman and it returned me data read from my local Azure Storage Emulator.

I then tried to recreate what I'd just done using JavaScript using the V1 functions creating the function via the azure-cli template with a minor alteration to read from my existing table.

The Problem

I started the function using func run TestGet and then tried to hit it using postman only to get an error:

Exception while executing function: Functions.TestGet -> Microsoft Azure WebJobs SDK 'MyStorageConnectionAppSetting' connection string is missing or empty. The Microsoft Azure Storage account connection string can be set in the following ways:
1. Set the connection string named 'AzureWebJobsMyStorageConnectionAppSetting' in the connectionStrings section of the .config file in the following format , or 
2. Set the environment variable named 'AzureWebJobsMyStorageConnectionAppSetting', or
3. Set corresponding property of JobHostConfiguration.

This confused me greatly as I had used the default AzureWebJobsStorage setting exactly as I had with the C# version which had worked.

Trying to Google the error message turned up next to no results and the majority of those didn't actually have any relevant infromation but this GitHub issue provided the clue to the answer specifically this comment which mention the IsEncrypted setting.

What I had noticed is that when the functions runtime started up the first line in the command window was The input is not a valid Base-64 string as it contains a non-base 64 character and so I checked my IsEncrypted setting

{
  "IsEncrypted": true,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true;"
  }
}

and found that it was set to true and due to that when the functions runtime ran up it wouldn't use the appsettings.json/local.settings.json as it expected them to be encrypted and since it wasn't it seems it wouldn't read the settings that were there, so setting it to false allowed the runtime to read the setting

The cause

A comment on the Github issue suggested that the IsEncrypted setting should be false so to  check if I had caused the issue or it had been the azure-cli I created a new folder and ran the command
func init which creates the basic files needed for functions including the appsettings.json which looks like this:

{
  "IsEncrypted": true,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true;"
  }
}

So it would seem the azure-cli is the cause of this issue and whilst you need to ensure the values should be encrypted when deployed to production/live when working locally you need them unencrypted to be able to work.

Why didn't it happen in Visual Studio?

I wanted to know why I hadn't run into this when I was creating functions in Visual Studio so went back into VS and created a new functions project and checked what had been created in the local.settings.json:

{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "AzureWebJobsDashboard": "UseDevelopmentStorage=true"
    }
}

As you can see it sets the IsEncrypted to false which is why I never had the problem with the C# functions.  As an experiment I set IsEncrypted to true and tried to run the functions and interestingly the functions runtime reported an error Failed to decrypt settings. Encrypted settings only be edited through 'func settings add'. which whilst not exactly clear does give a better phrase to search for.

Hopefully if anybody else runs into this problem they'll find it easier to resolve than I did.