Output from azd version
azd version 1.27.1 (commit 257908961d465e98c1a6574eae9624a7954b21cf)
Describe the bug
On an arm64 machine, if azd's managed bicep copy at $AZD_CONFIG_DIR/bin/bicep (~/.azd/bin/bicep) is the wrong architecture (e.g. an x86-64 binary left behind by an older/x64 install), azd up / provision hard-fails instead of recovering:
ERROR: deployment failed: step "provision" failed: initializing layer provision: failed to compile bicepparam template: ensuring bicep is installed: checking bicep version: exit code: 255, stdout: , stderr: qemu-x86_64: Could not open '/lib64/ld-linux-x86-64.so.2': No such file or directory
The native (arm64) azd binary runs fine — only the managed bicep is the wrong arch, so the OS tries to run it under qemu-x86_64 binfmt emulation, which fails because the x64 glibc loader isn't installed.
Root cause
In cli/azd/pkg/tools/bicep/bicep.go, ensureInstalled only downloads bicep when the file is missing:
if errors.Is(err, os.ErrNotExist) {
... downloadBicep(...)
}
cli.path = bicepPath
ver, err := cli.version(ctx) // runs `bicep --version`
if err != nil {
return fmt.Errorf("checking bicep version: %w", err) // <-- hard fail
}
When a (broken) binary already exists, azd skips the download, runs bicep --version, that fails to execute, and azd returns the error rather than replacing the bad binary. There is no self-heal path for a non-runnable / wrong-arch / corrupted managed bicep.
Note azd intentionally does not fall back to a bicep on PATH (no exec.LookPath) — it manages its own version-pinned copy (Version = 0.44.1), overridable only via AZD_BICEP_TOOL_PATH. That's by design for reproducibility, but it means a corrupt managed copy is a dead end without manual intervention.
Expected behavior
When the existing managed bicep fails its version check (can't execute — wrong arch, corrupted, or partial download), azd should re-download it once and retry, then fail only if the fresh copy still can't run. Freshly-downloaded binaries should not loop.
To reproduce
- On an arm64 Linux/WSL host, place an x86-64 bicep at
~/.azd/bin/bicep (or have one left from a prior x64 azd install).
- Run
azd up (or azd provision).
- Observe the
qemu-x86_64: Could not open '/lib64/ld-linux-x86-64.so.2' failure.
Environment
- arm64 WSL (Ubuntu, glibc).
uname -m = aarch64.
- azd is native arm64; the stale
~/.azd/bin/bicep was x86-64 (file reports ELF 64-bit LSB pie executable, x86-64).
- Deleting
~/.azd/bin/bicep makes azd re-download the correct bicep-linux-arm64 and resolves it (verified: bicep --version → 0.44.1).
Workarounds
rm ~/.azd/bin/bicep and re-run (azd re-downloads the correct arch), or
export AZD_BICEP_TOOL_PATH="$(command -v bicep)" to point azd at a working bicep on PATH (must be ≥ the pinned version).
Proposed fix
In ensureInstalled, track whether we just downloaded; if the version check fails on a pre-existing binary, re-download once (via the existing downloadBicep atomic temp-file+rename path) and re-check. Add a unit test that seeds a non-runnable file and asserts a single re-download + success.
Related
Output from
azd versionazd version 1.27.1 (commit 257908961d465e98c1a6574eae9624a7954b21cf)Describe the bug
On an arm64 machine, if azd's managed bicep copy at
$AZD_CONFIG_DIR/bin/bicep(~/.azd/bin/bicep) is the wrong architecture (e.g. an x86-64 binary left behind by an older/x64 install),azd up/provisionhard-fails instead of recovering:The native (arm64) azd binary runs fine — only the managed bicep is the wrong arch, so the OS tries to run it under
qemu-x86_64binfmt emulation, which fails because the x64 glibc loader isn't installed.Root cause
In
cli/azd/pkg/tools/bicep/bicep.go,ensureInstalledonly downloads bicep when the file is missing:When a (broken) binary already exists, azd skips the download, runs
bicep --version, that fails to execute, and azd returns the error rather than replacing the bad binary. There is no self-heal path for a non-runnable / wrong-arch / corrupted managed bicep.Note azd intentionally does not fall back to a
biceponPATH(noexec.LookPath) — it manages its own version-pinned copy (Version = 0.44.1), overridable only viaAZD_BICEP_TOOL_PATH. That's by design for reproducibility, but it means a corrupt managed copy is a dead end without manual intervention.Expected behavior
When the existing managed bicep fails its version check (can't execute — wrong arch, corrupted, or partial download), azd should re-download it once and retry, then fail only if the fresh copy still can't run. Freshly-downloaded binaries should not loop.
To reproduce
~/.azd/bin/bicep(or have one left from a prior x64 azd install).azd up(orazd provision).qemu-x86_64: Could not open '/lib64/ld-linux-x86-64.so.2'failure.Environment
uname -m=aarch64.~/.azd/bin/bicepwas x86-64 (filereportsELF 64-bit LSB pie executable, x86-64).~/.azd/bin/bicepmakes azd re-download the correctbicep-linux-arm64and resolves it (verified:bicep --version→0.44.1).Workarounds
rm ~/.azd/bin/bicepand re-run (azd re-downloads the correct arch), orexport AZD_BICEP_TOOL_PATH="$(command -v bicep)"to point azd at a working bicep onPATH(must be ≥ the pinned version).Proposed fix
In
ensureInstalled, track whether we just downloaded; if the version check fails on a pre-existing binary, re-download once (via the existingdownloadBicepatomic temp-file+rename path) and re-check. Add a unit test that seeds a non-runnable file and asserts a single re-download + success.Related