skip to Main Content

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


  1. 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.

    var basicProperties = {
      serverFarmId: serverfarm.outputs.serverfarmId
      httpsOnly: true
      redundancyMode: 'None'
      reserved: true
      siteConfig: siteConfig
    }
    

    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.

    param location string
    param resourceNamePrefix string
    param subnetResourceId string = ''
    
    module serverfarm 'appServicePlan.bicep' = {
      name: '${deployment().name}-AppSvcPlan'
      params: {
        resourceNamePrefix: resourceNamePrefix
        location: location
      }
    }
    
    resource function 'Microsoft.Web/sites@2021-02-01' = {
      name: '${resourceNamePrefix}-fn'
      location: location
      kind: 'functionapp,linux'
      properties: {
        serverFarmId: serverfarm.outputs.serverfarmId
        httpsOnly: true
        redundancyMode: 'None'
        reserved: true
        siteConfig: {
          linuxFxVersion: 'DOTNET-ISOLATED|6.0'
          http20Enabled: true
          alwaysOn: true
          ftpsState: 'Disabled'
          functionAppScaleLimit: 1
          minimumElasticInstanceCount: 1
          vnetRouteAllEnabled: !empty(subnetResourceId)
        }
        virtualNetworkSubnetId: !empty(subnetResourceId) ? subnetResourceId : null
      }
    }
    
    
    Login or Signup to reply.
  2. 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:

    Object reference not set to an instance of an object

    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:

    1. 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:

      for i in {1..10}
      do
      az deployment sub validate 
      --name mydeployment 
      --location westus3 
      --template-file main.bicep 
      --parameters @my-parameters.json
      done
      
    2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search