oven-sh/bun · error · Error

[azure] Image replication failed

Error message

[azure] Image replication failed: ${JSON.stringify(ver?.properties)}

What it means

Thrown while polling an Azure Compute Gallery image version (images/<definition>/versions/1.0.0) for replication: the loop in scripts/azure.mjs read provisioningState === "Failed" from the gallery API. The JSON of ver.properties is included so the failure reason is visible.

Solutions

  1. Inspect the properties JSON in the message for the exact failure code
  2. Check per-region replication status: az sig image-version show for the 1.0.0 version
  3. Delete the failed image version and re-run the image build so a fresh VM is captured
  4. Confirm the gallery and target region are healthy before retrying
Defensive patterns

Strategy: retry

Try / catch

try {
  await buildImage();
} catch (e) {
  if (e.message.includes("Image replication failed")) {
    await deleteImageVersion("1.0.0"); // a stuck Failed version blocks the same name
    return buildImage();
  }
  throw e;
}

Prevention

When it happens

Trigger: Capturing the VM into a gallery image version whose replication to the target region failed — source VM removed before capture finished, gallery storage errors, region outages, or limits on the gallery.

Common situations: The image-build VM was deallocated/terminated before provisioningState reached Succeeded; Azure gallery replication incidents; subscription gallery limits reached.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/df7b4fd2afdec0e5. Report an issue: GitHub.

Appendix: source

Thrown at scripts/azure.mjs:627

      await ensureImageDefinition(imageDefName, os, arch);

      // Create a single version "1.0.0" under this definition.
      await createImageVersion(imageDefName, "1.0.0", vmId);

      // Wait for image replication to complete before returning.
      // Single-region replication typically takes 5-15 minutes.
      const { galleryName } = config();
      const versionPath = `${rgPath()}/providers/Microsoft.Compute/galleries/${galleryName}/images/${imageDefName}/versions/1.0.0`;
      console.log(`[azure] Waiting for image replication...`);
      for (let i = 0; i < 120; i++) {
        const ver = await azureFetch("GET", versionPath, undefined, GALLERY_API_VERSION);
        const state = ver?.properties?.provisioningState;
        if (state === "Succeeded") {
          console.log(`[azure] Image ready: ${imageDefName}/1.0.0`);
          break;
        }
        if (state === "Failed") {
          throw new Error(`[azure] Image replication failed: ${JSON.stringify(ver?.properties)}`);
        }
        if (i % 6 === 0) {
          console.log(`[azure] Image replicating... (${i}m elapsed)`);
        }
        await new Promise(r => setTimeout(r, 10_000));
      }

      return label;
    };

    const terminate = async () => {
      await deleteVm(vmName);
      // Resources with deleteOption=Delete are cleaned up automatically
      // But clean up anything that might be left
      await deleteNic(nicName);
      await deletePublicIp(publicIpName);
    };

View on GitHub (pinned to 8c5296ac45)