Skip to content

azd up fails: BCP420 in infra/core/host/container-apps.bicep - ternary module scope no longer compiles on Bicep 0.36.1+ #66

Description

@hemarina

Describe the bug

azd up fails during provisioning because infra/core/host/container-apps.bicep no longer compiles with current versions of the Bicep CLI:

ERROR: Your Bicep template has an error.

error executing step command 'provision': deployment failed: initializing provisioning manager:
failed to compile bicep template: failed running bicep build: exit code: 1, stdout: , stderr:
infra\core\host\container-apps.bicep(28,10) : Error BCP420: The scope could not be resolved at
compile time because the supplied expression is ambiguous or too complex. Scoping expressions must
be reducible to a specific kind of scope without knowledge of parameter values.
[https://aka.ms/bicep/core-diagnostics#BCP420]
infra\main.bicep(218,22) : Error BCP104: The referenced module has errors.
[https://aka.ms/bicep/core-diagnostics#BCP104]

The BCP104 in main.bicep is just the cascade from the single real error. The rest of the bicep build output is pre-existing warnings (BCP318 / BCP037 / BCP187 / linter), which are unrelated to the failure.

Root cause

infra/core/host/container-apps.bicep:28 sets a module scope with a ternary that returns two different scope expressions:

module containerRegistry 'container-registry.bicep' = {
  name: '${name}-container-registry'
  scope: !empty(containerRegistryResourceGroupName) ? resourceGroup(containerRegistryResourceGroupName) : resourceGroup()
  ...
}

Bicep turned this pattern into a hard compile error (BCP420) in v0.36.1 (June 2025). A scope: expression must now reduce to a specific scope kind without knowledge of parameter values.

References:

This compiled fine when the template was authored, so nothing changed in this repo — the toolchain moved. Notably there is no "pin an older Bicep" workaround for azd users: azd pins Bicep 0.45.15 and automatically upgrades any older local copy it manages (cli/azd/pkg/tools/bicep/bicep.go), so every user hits this.

This file is the legacy infra/core/ shared library used across many azd samples, so other templates carrying the same copy of core/host/container-apps.bicep are likely affected too.

To Reproduce

  1. azd init -t Azure-Samples/APICenter-Reference
  2. azd up

Or, without deploying anything:

bicep build infra/main.bicep

Expected behavior

azd up succeeds.

Suggested fix

Collapse the ternary so a single resourceGroup() call determines the scope kind and only the name varies:

module containerRegistry 'container-registry.bicep' = {
  name: '${name}-container-registry'
  scope: resourceGroup(!empty(containerRegistryResourceGroupName) ? containerRegistryResourceGroupName : resourceGroup().name)
  ...
}

I verified this against Bicep 0.45.15 (the version azd pins): the original expression reproduces BCP420 at the same line/column, and the revised expression compiles cleanly (exit code 0).

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions