Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Infrastructure as Code By James Joyner IV · · 7 min read

Bicep Error: 'BCP028: Identifier "storageAccount" is declared multiple times' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix Bicep 'Error BCP028: Identifier "storageAccount" is declared multiple times. Remove or rename the duplicates' by finding and renaming duplicate symbols.

  • #iac
  • #infrastructure-as-code
  • #bicep
  • #troubleshooting
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

BCP028 is a compile-time error raised by the Bicep CLI before anything is sent to Azure. Every symbolic name in a Bicep file — a param, var, resource, module, output, or type declaration — must be unique within that file. When two declarations share the same identifier, Bicep cannot decide which one a later reference means, so it refuses to build.

The error looks like this:

main.bicep(31,10) : Error BCP028: Identifier "storageAccount" is declared multiple times. Remove or rename the duplicates. [https://aka.ms/bicep/core-diagnostics#BCP028]

The (31,10) is line 31, column 10 — the location of one of the offending declarations. Bicep will typically emit BCP028 once per duplicate occurrence, so you may see the same identifier flagged at several lines. This is a pure naming collision; it is not about resource names in Azure (the name: property), only about the Bicep symbolic names you use to reference declarations inside the file.

Symptoms

  • az bicep build or az deployment group create fails immediately with Error BCP028 and a line/column reference.
  • The same identifier is flagged on two or more lines.
  • VS Code’s Bicep extension underlines the duplicate names in red before you ever run a command.
  • No ARM JSON is produced — the build never completes, so the deployment never starts.

Common Root Causes

1. Two resources given the same symbolic name

The classic case: copy-pasting a resource block and forgetting to rename the symbol. Both blocks are valid on their own, but they share storageAccount.

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: 'examplestordata'
  location: location
  // ...
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: 'examplestorlogs'   // BCP028: "storageAccount" declared twice
  location: location
}

2. A param and a var (or resource) sharing a name

Symbols share one namespace. A param named location and a var location = ... collide even though they are different kinds of declaration.

param storageAccount string
var storageAccount = 'examplestor'   // BCP028

3. Duplicate output or module names

Two output blocks or two module declarations reusing an identifier hit the same rule.

module network 'network.bicep' = { name: 'net1', params: {} }
module network 'network.bicep' = { name: 'net2', params: {} }  // BCP028

4. Merged files or bad rebase

Concatenating two Bicep snippets, or a Git merge that duplicated a block, silently reintroduces a name that already exists elsewhere in the file.

5. Loop variable colliding with an outer symbol

A for loop item variable (e.g. for storageAccount in accounts) that reuses the name of a top-level declaration.

How to Diagnose

Step 1: Read the line/column the compiler gives you

az bicep build --file main.bicep

The main.bicep(31,10) coordinate points at one occurrence. Jump there first.

Step 2: Find every occurrence of the identifier

Search the whole file (and any files you merged in) for the declaration keyword plus the name:

grep -nE '(resource|param|var|module|output|type)[[:space:]]+storageAccount\b' main.bicep

This lists every line that declares storageAccount, ignoring the many lines that merely reference it.

Step 3: Confirm with the language server

Open the file in VS Code with the Bicep extension. Duplicate symbols are underlined, and “Go to Definition” on the name will show multiple targets — a fast way to spot the second declaration you missed.

Fixes

Rename one of the declarations

Give each declaration a distinct, descriptive symbol and update its references:

resource dataStorageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: 'examplestordata'
  location: location
}

resource logStorageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: 'examplestorlogs'
  location: location
}

Collapse duplicates into a loop

If you truly wanted several near-identical resources, use a single declaration with a for loop instead of copy-pasting:

param storageNames array = [ 'examplestordata', 'examplestorlogs' ]

resource storageAccounts 'Microsoft.Storage/storageAccounts@2023-01-01' = [for name in storageNames: {
  name: name
  location: location
  sku: { name: 'Standard_LRS' }
  kind: 'StorageV2'
}]

Remove the accidental duplicate

If a merge or paste created a straight duplicate, delete the redundant block and rebuild:

az bicep build --file main.bicep && echo "compiles clean"

What to Watch Out For

  • Symbolic names share a single namespace across param, var, resource, module, output, and type — a name used once anywhere is used up.
  • Don’t confuse the symbolic name with the Azure name: property; BCP028 is only about the former, and two resources can share neither symbol.
  • After a Git merge, run az bicep build before committing — merges are a frequent source of duplicated declarations.
  • Adopt a naming convention (dataStorageAccount, logStorageAccount) so copy-paste collisions are obvious on sight.
  • Prefer loops over copy-pasted resource blocks when you need multiple similar resources; it removes the whole class of duplicate-symbol bugs.
Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.