SafeLinks Protection for Links Generated by M365 Copilot Chat and Office Apps
May 6, 2025Smart Auditing: Leveraging Azure AI Agents to Transform Financial Oversight
May 6, 2025Have you ever come across a scenario where you want to enforce a parameter to have a certain value because another parameter has value X? This means you’re dealing with a conditional parameter and need to validate the input before continuing the deployment. In Azure Bicep, it’s now possible to create conditional parameters and let the deployment fail when a condition is not met.
In this blog, you will learn how to use the fail()
function in Azure Bicep to conditionally fail deployments.
What does fail() do?
The fail function is known as a flow control function. This means it can be used to influence the execution of your Azure Bicep deployment. You can deliberately fail a deployment, for example, if certain conditions are not met.
The fail function fail(message: string)
expects one parameter: a descriptive message explaining why the deployment failed. This message will be shown in the error output. The function is evaluated at runtime, meaning the error will only occur during the actual deployment, not at compile time.
output outFail string = fail('This is the descriptive message why the deployment has failed.')
When you deploy the Bicep snippet above, the deployment will fail, and you will receive an error message like this:


Fail() in action
In the example below, the module has three parameters:
parVirtualNetworkParentName
: the name of the virtual network where the subnet should be deployed.parAddressPrefix
: used to configure the subnet with a single address prefix. This parameter is conditional and must be set whenparAddressPrefixes
is null.parAddressPrefixes
: used to configure the subnet with a list of address prefixes. This parameter is conditional and must be set whenparAddressPrefix
is null.
Both parameters parAddressPrefix
and parAddressPrefixes
are optional, but you cannot specify both at the same time. One of them must be provided.
Before the fail()
function existed, this could lead to issues such as the user assigning both parameters, which might result in an unexpected subnet configuration. But now, with the fail() function, you can control the deployment flow: if both (or neither) parameters are provided, you can raise an error and stop the deployment with a custom error message.
The variable varIsAddressConditionValid
performs checks to determine whether both parameters are empty or if both have been provided. If either condition is true, the fail()
function is triggered, and the deployment will fail. If the validation passes, the variable returns null, allowing the fallback value from either parAddressPrefix
or parAddressPrefixes
to be used.
.gist table { margin-bottom: 0; }
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@description(‘Required. Name of the parent virtual network.’) | |
param parVirtualNetworkParentName string | |
@description(‘Conditional. The address prefix of the subnet. Required when parAddressPrefixes is null.’) | |
param parAddressPrefix string? | |
@description(‘Conditional. The address prefixes of the subnet. Required when parAddressPrefix is null.’) | |
param parAddressPrefixes string[]? | |
var varIsAddressConditionValid = empty(parAddressPrefix) && empty(parAddressPrefixes) | |
? fail(‘Either parAddressPrefix or parAddressPrefixes must be provided.’) | |
: !empty(parAddressPrefix) && !empty(parAddressPrefixes) | |
? fail(‘Provide either parAddressPrefix or parAddressPrefixes, not both.’) | |
: null | |
resource resSubnet ‘Microsoft.Network/virtualNetworks/subnets@2024-05-01’ = { | |
name: ‘${parVirtualNetworkParentName}/my-subnet’ | |
properties: { | |
addressPrefix: varIsAddressConditionValid ?? parAddressPrefix | |
addressPrefixes: varIsAddressConditionValid ?? parAddressPrefixes | |
} | |
} |
If neither parameter is set, it will throw the error Either parAddressPrefix or parAddressPrefixes must be provided
:

Another use case could be to fail the deployment when a user adds a prefix, such as kv-
to a resource name, even though your module already handles prefixes. In this case, you want to prevent the user from doing that. Below is an example of how to use fail() in this scenario:
.gist table { margin-bottom: 0; }
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@description(‘Required. Name of the resource.’) | |
param parKeyVaultName string | |
@description(‘Optional. Location of the resource.’) | |
param parLocation string = resourceGroup().location | |
var varRequiredPrefix = ‘kv-‘ | |
var varKeyVaultNameWithPrefix = startsWith(parKeyVaultName, varRequiredPrefix) | |
? fail(‘This module prefixes the key vault name with: “${varRequiredPrefix}”. Remove the prefix from the parameter file.’) | |
: ‘${varRequiredPrefix}${parKeyVaultName}’ | |
resource resKeyVault ‘Microsoft.KeyVault/vaults@2024-11-01’ = { | |
name: varKeyVaultNameWithPrefix | |
location: parLocation | |
properties: { | |
sku: { | |
name: ‘standard’ | |
family: ‘A’ | |
} | |
tenantId: subscription().tenantId | |
} | |
} |
The output when parKeyVaultName
contains the prefix:

Conclusion
There are many use cases for incorporating fail()
into your Bicep templates. It adds an extra layer of validation, allowing you to control the deployment flow based on specific logic. By triggering a deployment failure on demand, you can enforce rules and provide clear error messages to guide users in configuring the parameters correctly. This function is great to provide custom error messages for your Azure Bicep building blocks, for example.