Below I’ve added the contents of 3 Bicep files. If you add these to the same directory and run a subscription-based deployment to Azure as follows…
az deployment sub create --name "VerifyBug" --location "northeurope" --template-file .main.bicep
…you’ll get a "Object reference not set to an instance of an object". I’ve just spent the best part of 24 hours trying to work out what exactly was causing this exception because it was coming from a much larger deployment that this replicates. There is no indication of where the exception is being thrown.
What I’ve found is that the problem is with the serverfarm.outputs.serverfarmId
value. See how this is being used in an object which is later unioned with another object. It seems the problem is a combination of using an ARM output inside a union operator, but I’d love a more technical explanation. I’m mainly posting this here to help anyone else avoid similar pain in the future.
The solution I’ve found is to break everything after the serverfarm
module out of function.bicep into a separate module which takes the server farm ID as a parameter. Everything then works, but I’d love to hear an explanation about why this is.
main.bicep
targetScope = 'subscription'
var location = 'northeurope'
var resourceNamePrefix = 'test-resource'
resource resourceGroup 'Microsoft.Resources/resourceGroups@2020-10-01' = {
name: '${resourceNamePrefix}-rg'
location: location
}
module func 'function.bicep' = {
name: '${deployment().name}-Func'
scope: resourceGroup
params: {
resourceNamePrefix: resourceNamePrefix
location: location
}
}
function.bicep
param location string
param resourceNamePrefix string
param networking object = {}
module serverfarm 'appServicePlan.bicep' = {
name: '${deployment().name}-AppSvcPlan'
params: {
resourceNamePrefix: resourceNamePrefix
location: location
}
}
var siteConfig = {
linuxFxVersion: 'DOTNET-ISOLATED|6.0'
http20Enabled: true
alwaysOn: true
ftpsState: 'Disabled'
functionAppScaleLimit: 1
minimumElasticInstanceCount: 1
vnetRouteAllEnabled: !empty(networking)
}
var basicProperties = {
serverFarmId: serverfarm.outputs.serverfarmId
httpsOnly: true
redundancyMode: 'None'
reserved: true
siteConfig: siteConfig
}
var networkingProperties = empty(networking) ? {} : {
virtualNetworkSubnetId: networking.subnetResourceId
}
var functionProperties = union(basicProperties, networkingProperties)
resource function 'Microsoft.Web/sites@2021-02-01' = {
name: '${resourceNamePrefix}-fn'
location: location
kind: 'functionapp,linux'
properties: functionProperties
}
appServicePlan.bicep
param resourceNamePrefix string
param location string
resource serverfarm 'Microsoft.Web/serverfarms@2021-02-01' = {
kind: 'linux'
name: '${resourceNamePrefix}-appserviceplan'
location: location
sku: {
name: 'S1'
tier: 'Standard'
}
properties: {
reserved: true
maximumElasticWorkerCount: 1
}
}
output serverfarmId string = serverfarm.id
2
Answers
It is because "Resource Manager resolves variables before starting the deployment operations." Reference.
In the following part, the Resource Manager is trying to resolve
serverFarmId: serverfarm.outputs.serverfarmId
but it doesn’t exist yet.Revised function.bicep
Here I removed the variables and reconstructed the
resource
deployment, then I changed the parameter from a virtual network object to a string with the subnet ID. I’ve had better results working with empty strings than objects. I ran the deployment and it worked without error.Solution
Switching the deployment region to another location solved the issue in my case.
Explanation
The bellow error message could randomly happen in some Azure location:
For instance, the above error message randomly occurred at validation time in the
brazilsouth
Azure location, sometimes it worked and sometimes it didn’t. Thus, switching to another region solved the issue.The important part is how to track down the issue:
Since the issue happens randomly at validation time, I suggest to validate the deployment multiple times (even if it works the first few times). You could use the following script to easy the process:
Once you validated multiple times against a region where the mentioned issue,
Object reference not set to an instance of an object
, does not happen, update the deployment to that region.