Back to Blog
May 12, 2026

Azure Bicep Updates — May 2026 Edition: Retry Decorators, String Functions, and Registry Guardrails

Share

Azure Bicep Updates — May 2026 Edition: Retry Decorators, String Functions, and Registry Guardrails

Date: 2026-05-12

Discover how the May 2026 Azure Bicep update enhances deployment reliability with retryOn decorators, streamlines templates using like() and distinct() functions, and tightens security with trusted registries.

Tags: ["Azure", "Bicep", "Infrastructure as Code", "DevOps", "CloudSecurity"]

Azure Bicep continues to evolve as a powerful infrastructure-as-code (IaC) domain-specific language, helping developers simplify resource deployments on Azure. In May 2026, the team surprised us by rolling out two releases packed with features that improve reliability, authoring ergonomics, and security guardrails.

One highlight is the introduction of the retryOn decorator—finally answering a user request from 2020—enabling retry logic on deployment errors. Alongside that, Bicep now supports two handy new functions for array and string operations: like() and distinct(). These small but practical additions can optimize your templates for naming conventions and data deduplication.

This update also tightens security boundaries by enforcing a trusted registry whitelist for OCI module restoration. And, enhanced linting rules catch common mistakes like unknown resource types or superfluous module names before deployment.

In this post, we’ll explore these key changes and their practical impact. We'll dissect the new retry decorator, examine the new functions with a real-world example, review improvements in linting and snapshot commands, and decode the consequences of the registry whitelist enforcement.

Architecture Overview

┌─────────────────────────────────────────────┐
│               Developer Workflow             │
├─────────────────────────────────────────────┤
│  • Author Bicep Templates                     │
│  • Use new functions: like(), distinct()     │
│  • Apply retryOn decorator for resilience    │
│  • Run linting rules to catch errors         │
└─────────────────────────────────────────────┘
                ↓
┌─────────────────────────────────────────────┐
│             Bicep Compiler & CLI             │
├─────────────────────────────────────────────┤
│  • Compile templates to ARM JSON             │
│  • Enforce trusted OCI registry list         │
│  • Produce richer snapshot outputs            │
│  • Validate with enhanced linting rules       │
└─────────────────────────────────────────────┘
                ↓
┌─────────────────────────────────────────────┐
│               Azure Deployment                │
├─────────────────────────────────────────────┤
│  • Deploy ARM templates to Azure             │
│  • Retry deployments on specified error codes│
│  • Manage resources with policy & guardrails │
└─────────────────────────────────────────────┘

This flow captures how authoring improvements feed straight into safer, more reliable deployments controlled by the Bicep tooling and Azure platform.

Azure Bicep May 2026 update graphic
Illustration of Azure Bicep May 2026 update from idontlikeai.dev

Key Technical Observations

  • RetryOn Decorator Fulfills a Long-Standing User Demand — After six years of discussion starting from issue #1013 on GitHub, Bicep introduces @retryOn, enabling declarative retry strategies on deployment errors using specific ARM error codes. This brings operational stability not natively available in ARM templates.

  • Introduction of Pattern Matching and Deduplication Functions — The like() function supports * wildcard string pattern matching, ideal for enforcing naming conventions dynamically. The distinct() function removes duplicates while preserving input order, enabling clean generation of resource child arrays like IP rules or tags.

  • Linting Now Flags Unknown Resource Types and Extraneous Module Names — The use-recognized-resource-type rule helps catch typos or unsupported custom resource types early, improving deployment quality checks. The no-module-name rule encourages simpler module syntax by removing unnecessary explicit names.

  • Snapshot Command Gains Predictable Outputs and Management Group Parameter — Now snapshotting resolves all compile-time expressions and retains unresolved ARM expressions as-is, producing more useful, reviewable JSON artifacts. The management group ID parameter aids platform engineering scenarios at scale.

  • Trusted Registry List Enforcement Changes Module Restoration Semantics — Bicep blocks OCI module restores from registries outside built-in trusted domains (e.g., *.azurecr.io, mcr.microsoft.com, ghcr.io), raising BCP446 errors on unapproved registries. This prevents supply-chain risks but requires adjustments for custom domain ACRs.

How It Works

The RetryOn Deployment Decorator

A common challenge in ARM template deployments is intermittent failures caused by transient backend states or locking conflicts. The newly introduced @retryOn decorator addresses this by allowing the template author to specify error codes on which deployment resources should be retried.

Usage syntax:

@retryOn(['<errorCode>'], <retryTimes>)
  • The first parameter is an array of ARM error codes to watch for.
  • The optional second parameter specifies the number of retry attempts.

For example, you could instruct your resource deployment to retry if it hits a Conflict error due to a resource lock contention:

@retryOn(['DeploymentFailed'], 3)
resource myResource 'Microsoft.Resources/deployments@2025-01-01' = {
  // resource details
}

The exact error codes can be found via the official ARM error list or by diagnostics.

This feature allows templates to be more resilient without external scripting or manual intervention.

Practical Array and String Operators: like() and distinct()

These functions don't necessitate template rewrites but become invaluable once discovered.

  • like() performs wildcard pattern matching on strings with *. This is perfect for conditional logic based on naming conventions:
var isProduction = like(workloadName, 'prod-*')
  • distinct() removes duplicate entries from an array, preserving order. This helps prevent redundant resource definitions or permissions:
var uniqueAllowedIpAddresses = distinct(allowedIpAddresses)

Here's a real-world snippet illustrating these functions applied in a storage account scenario:

param location string = resourceGroup().location
param workloadName string

param allowedIpAddresses array = [
    '203.0.113.10'
    '198.51.100.25'
    '203.0.113.10'
]

var isProduction = like(workloadName, 'prod-*')
var uniqueAllowedIpAddresses = distinct(allowedIpAddresses)

resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
    name: '${replace(workloadName, '-', '')}st001'
    location: location
    sku: {
        name: isProduction ? 'Standard_ZRS' : 'Standard_LRS'
    }
    kind: 'StorageV2'
    properties: {
        minimumTlsVersion: 'TLS1_2'
        allowBlobPublicAccess: false
        publicNetworkAccess: 'Enabled'
        networkAcls: {
            defaultAction: 'Deny'
            bypass: 'AzureServices'
            ipRules: [for ipAddress in uniqueAllowedIpAddresses: {
                action: 'Allow'
                value: ipAddress
            }]
        }
    }
}

output productionWorkload bool = isProduction
output configuredIpRules array = uniqueAllowedIpAddresses

This snippet dynamically sets storage SKU based on workload naming and cleans IP rules to avoid duplicates derived from cross-team inputs.

Enhanced Guardrails: Linting Rules and Snapshot

Two new lint rules improve template quality:

  • use-recognized-resource-type: Validates types against Azure’s registry to detect typos (e.g., storageAcounts vs. storageAccounts) and warns on unknown custom resources. Example catch:
output keys object = listKeys(resourceId('Microsoft.Storage/storageAcounts', storageAccountName), '2025-08-01')
  • no-module-name: Discourages explicit module names which are redundant:
module networking './modules/networking.bicep' = {
    name: 'networking'  // flagged
    params: {
        location: resourceGroup().location
    }
}

Preferred:

module networking './modules/networking.bicep' = {
    params: {
        location: resourceGroup().location
    }
}

The snapshot command now produces outputs with resolved values where possible, embedding unresolved ARM expressions in a more structured manner. It also supports specifying a management group ID for scoped deployments:

targetScope = 'managementGroup'

param policyAssignmentName string
param policyDefinitionId string

resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
    name: policyAssignmentName
    properties: {
        policyDefinitionId: policyDefinitionId
    }
}

output policyAssignmentId string = policyAssignment.id

CLI example:

bicep snapshot main.bicepparam --mode overwrite --management-group-id platform --location westeurope

This facilitates better auditing and artifact management in enterprise pipelines.

Trusted OCI Registry Enforcement

To mitigate supply chain vulnerabilities, Bicep now locks down module restoration to a fixed set of trusted registries:

*.azurecr.io
*.azurecr.cn
*.azurecr.us
mcr.microsoft.com
mcr.azure.cn
ghcr.io

Attempts to restore from any other registry, even if it is a valid Azure Container Registry but using a custom domain (e.g., moduleStore.myCompany.com), will be blocked with a BCP446 error.

If you use custom domains for Azure Container Registries, you’ll need to switch back to the default login server format.

You can retrieve your ACR login server domain with PowerShell:

# Requires Az.ContainerRegistry
$registry = Get-AzContainerRegistry -ResourceGroupName <resourceGroupName> -Name <registryName>

$registry.LoginServer

This security step enhances module provenance guarantees, reinforcing trusted supply chain principles.

Quick Tips & Tricks

  1. Use retryOn to Smooth Out Transient Deployment Failures
    Implement @retryOn on resources where frequent transient errors occur due to locks or backend conflicts. This reduces manual re-deployment.

  2. Leverage like() for Conditional Logic Based on Naming
    Simplify complex conditionals by pattern matching on string inputs instead of passing extra flags. For example, test workload prefixes like 'prod-*'.

  3. Clean Input Arrays with distinct() Before Resource Generation
    Avoid duplication bugs by deduplicating arrays used in tags, IP rules, or role assignments early in your Bicep code.

  4. Enable use-recognized-resource-type Lint Rule to Catch Typos Early
    Prevent frustrating runtime deployment errors by adding this guardrail to your CI pipeline.

  5. Drop Explicit Module Names with no-module-name for Cleaner Syntax
    Keep templates concise and avoid unnecessary duplication.

  6. Confirm Your Registry Login Server Before Using Modules with OCI
    Run PowerShell or Azure CLI commands to get the exact registry domain and ensure your module references comply with trusted registries.

Conclusion

The May 2026 Azure Bicep releases deliver a thoughtful blend of productivity, resilience, and security improvements. The new retryOn decorator empowers templates to handle transient errors natively, dramatically improving deployment robustness. Meanwhile, fresh functions like like() and distinct() enable more expressive and efficient template logic with minimal effort.

Guardrails in linting and snapshotting tighten the authoring experience, catching errors early and improving artifact traceability in complex pipelines. Finally, the enforcement of trusted OCI registries marks a critical security milestone ensuring module provenance.

Together, these changes reinforce Bicep’s position as a maturing, enterprise-ready IaC toolset. As cloud environments grow more complex, such incremental yet impactful enhancements let teams deploy confidently and securely without sacrificing agility.

References

  1. Azure Bicep Updates — May 2026 Edition — Original article detailing the release.
  2. Add "wait" and "retry" deployment options GitHub issue #1013 — Community discussion and examples of retryOn.
  3. ARM Common Deployment Errors and Codes — Comprehensive ARM error code reference.
  4. Bicep v0.43.1 Release Notes — Contains most new functions and lint rules.
  5. Get-AzContainerRegistry - PowerShell Documentation — Reference for discovering ACR details.