Ken Muse

Bicep and APIM Template Not Found


It’s always nice when everything works exactly as documented. Unfortunately, as we’ve already seen that’s rarely always how everything works out. For example, let’s look at working with Azure API Management using Bicep. Bicep utilizes the published schemas for the services to provide code completion and validation. In most cases, that works well and saves developer time. Of course, for that to work the schema must be accurate and up-to-date. Not all of the published schema are correct. Unfortunately for us, APIM templates are one of those cases.

The service schema indicates that the template names must be camel-cased. The first letter of each word after the first should be uppercase and every other letter should be lowercase. As a result, a Bicep definition for one of those templates may look like this:

1resource apimAccountClosedDeveloper 'Microsoft.ApiManagement/service/templates@2021-08-01' = {
2  parent: apimService
3  name: 'accountClosedDeveloper'
4  properties: {
5      // body and parameters for the template
6  }

Bicep will validate the file as correct, but when you try to deploy the template you will receive an error message from ARM:

1{
2    "status": "Failed",
3    "error": {
4        "code": "ResourceNotFound",
5        "message": "Template not found."
6    }
7}

As you probably guessed, the root cause is an incorrect schema. The service requires you to use a template name that is Pascal-cased. That is, the first letter of EVERY word must be uppercase.

Naturally, the fix seems simple — correct the Bicep template:

1resource apimAccountClosedDeveloper 'Microsoft.ApiManagement/service/templates@2021-08-01' = {
2  parent: apimService
3  name: 'AccountClosedDeveloper'
4  properties: {
5      // body and parameters for the template
6  }

Unfortunately, that doesn’t work either. Bicep relies on the schema definition, so you receive a BCP088 error. You are notified that you must use one of the specified camel cased names. At this point, you might think to use the new #disable-next-line feature. Unfortunately, it doesn’t work for this error (as of Bicep v0.4.1124). Because this is an error, it prevents Bicep from deploying the template or generating an ARM Template.

Working around this issue with Bicep requires us to take advantage of one of the built-in functions. While a surprising number of the functions allow validation to proceed, some do not. One of those is split. Bicep cannot currently validate the output of that function in order to be able to raise an error. We can take advantage of this to change how we define the name. If we split on a non-existant character, we’ll get an array with a single element. If we reference that element, we can get the original data while avoiding the validation logic. Yes, it’s a hack … but it’s a hack that allows you to create a working template. Modifying the name allows us to create a working scenario:

1name: split('AccountClosedDeveloper', '~')[0]

Since Bicep cannot validate the content of the first element of the array, it does not generate an error. The output of this function is identical to the input, so it makes it very easy to see the actual value.

I raised an issue in the ARM Schemas repo, which Microsoft is tracking in the Azure REST API Specs repo on GitHub. Once this is resolved, the workaround won’t be necessary. That said, it will continue to work even after the fix.

Happy DevOp’ing!