Deploying Azure Resource Manager (ARM) templates with the Azure PowerShell command New-AzureRmResourceGroupDeployment can fail for a variety of reasons. One of the more confusing situations can occur when handling template validation errors (Code=InvalidTemplateDeployment). This is because sometimes additional context is missing from the Exception and you have to lookup more information into order to troubleshoot the issue. In this post we will take a closer look at this particular error and how to resolve it.
First, remember that there is an important distinction between a template validation error, and a template deployment error. A template validation error means there is a problem with the syntax or layout of your deployment template– this prevents the deployment from starting. A template deployment error means that your template syntax has been approved, but an error has occurred while provisioning the resources.
TIP: If a template validation error occurs, no deployment record will be available in the history of the resource group deployments– because the deployment never actually started.
Reproduce the problem
Let’s start off with a bad Azure Resource Manager (ARM) template– one that I know has a syntax error in it. In this case, a required property is missing.
Example invalid template:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": { },
"variables": { },
"functions": [ ],
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "storagetest55123",
"apiVersion": "2018-02-01",
"location": "westus2",
"properties": {
"supportsHttpsTrafficOnly": true
}
}
],
"outputs": { }
}
We then initiate the deployment in PowerShell:
$ErrorActionPreference = 'Stop'
# login (if you haven't already)
Login-AzureRmAccount
# create the resource group (if you haven't already)
New-AzureRmResourceGroup -Name 'deploytest-resources' -Location 'westus2'
# run the deployment
New-AzureRmResourceGroupDeployment -ResourceGroupName 'deploytest-resources' -TemplateFile '.\template-validation-error.json'
After running the above commands, the validation fails and the template is never deployed. We receive this error message:
New-AzureRmResourceGroupDeployment : 12:16:21 PM - Error: Code=InvalidTemplateDeployment; Message=The template deployment
'<deployment name>' is not valid according to the validation procedure. The tracking id is 'be6813f8-1f8f-4134-bc88-611765ed6cf8'. See
inner errors for details. Please see https://aka.ms/arm-deploy for usage details.
At line:1 char:1
+ New-AzureRmResourceGroupDeployment -ResourceGroupName 'deploytest-res ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-AzureRmResourceGroupDeployment], Exception
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureResourceGroupDeploymentCmdlet

The problem with the above error message is that it tells us there is a validation error, but it doesn’t tell us which resource caused the problem, or the specific property or syntax error that caused the failure. It does however leave behind a CorrelationID, which can be used to look up more information.
Part of this issue can be blamed on our Execution Policy handling. The New-AzureRmResourceGroupDeployment command will normally write multiple error records in a failure situation like this one. Some of those errors may contain the additional context we are looking for. However since we have enforced ‘Stop’ as the error action, this is the single error that bubbles up– missing important context we need to resolve the issue.
The following are some solutions for how to grab the additional context regardless of your error handling / execution policy settings.
Solution 1: View additional context in the Azure Portal
Click on the notifications bell icon in the top right of the Azure Portal, and then click on ‘More events in the activity log’.

Find your recent deployment validation error in the history, then click on it.

Under the properties section of the document, you can see the request result, including a status message. That status message contains the specific context we were looking for– which is the fact that the ‘accountType’ field is missing from the storage account in my template. We could then go fix the ARM template by adding the missing field.

Solution 2: View additional context in Azure PowerShell
You can do the same thing in PowerShell by running the following command to retrieve that activity log entry by correlation ID. Substitute the GUID in this command with the one provided to you in the error message you received.
Get-AzureRmLog -CorrelationId 'be6813f8-1f8f-4134-bc88-611765ed6cf8'

TIP: Calling Get-AzureRmLog with your correlation ID immediately after the deployment has failed may return no results. It takes a few seconds for the records to be ingested/available, so you may need smart retry functionality if collecting this error from within automated deployment scripts.
Solution 3: Run the deployment manually with the -Debug switch
Yet another option to try is to get the error in real time by stepping through the Azure command in debug mode. This prompts at several points along the way and provides extra verbose output, including the response back from Azure about your template validation result. Start the command and keep hitting continue until you reach the web response.
# runs the deployment with debugging enabled
New-AzureRmResourceGroupDeployment -ResourceGroupName 'deploytest-resources' -TemplateFile '.\template-validation-error.json' -Debug

Template API reference
One final tip to avoid template syntax and validation errors is to always consult the Azure docs ARM template API reference (found here). It contains detailed schema information about each ARM template resource, outlines which properties are required or optional, and provides this information for each API revision.
In our examples above we were trying to deploy a storage account using API version 2018-02-01. By consulting that resource’s API reference, we can tell exactly what we did wrong with our schema.