{"record":{"id":"56523c9ca74ccc35","repo":"oven-sh/bun","slug":"azure-method-path-failed-after-3-retries","errorCode":null,"errorMessage":"[azure] ${method} ${path} failed after 3 retries","messagePattern":"\\[azure\\] (.+?) (.+?) failed after 3 retries","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/azure.mjs","lineNumber":143,"sourceCode":"      if (operationUrl) {\n        return waitForOperation(operationUrl);\n      }\n    }\n\n    if (response.status === 204) {\n      return null;\n    }\n\n    if (!response.ok) {\n      const text = await response.text();\n      throw new Error(`[azure] ${method} ${path} failed: ${response.status} ${text}`);\n    }\n\n    const text = await response.text();\n    return text ? JSON.parse(text) : null;\n  }\n\n  throw new Error(`[azure] ${method} ${path} failed after 3 retries`);\n}\n\nasync function waitForOperation(operationUrl, maxWaitMs = 3_600_000) {\n  const start = Date.now();\n  let fetchErrors = 0;\n\n  while (Date.now() - start < maxWaitMs) {\n    const token = await getAccessToken();\n\n    let response;\n    try {\n      response = await fetch(operationUrl, {\n        headers: { Authorization: `Bearer ${token}` },\n      });\n    } catch (err) {\n      fetchErrors++;\n      if (fetchErrors > 10) {\n        throw new Error(`[azure] Operation poll failed after ${fetchErrors} fetch errors`, { cause: err });","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/azure.mjs#L125-L161","documentation":"The REST helper attempted the call 3 times and every attempt hit a retryable condition (the loop retries transient statuses before reaching this throw), so the request never got a final answer. This is exhaustion of the fixed 3-attempt budget rather than a single hard failure.","triggerScenarios":"Azure ARM continuously returning retryable statuses (429 throttling, 5xx) for all three attempts; backoff between attempts too short relative to the throttle window.","commonSituations":"Subscription-level throttling during heavy parallel image builds; an Azure regional incident lasting longer than the retry budget.","solutions":["Wait and re-run — transient Azure throttling usually clears","Space out concurrent azure.mjs jobs hitting the same subscription/resource group","Raise the retry count or backoff in the request helper if the workload is legitimately bursty"],"exampleFix":"// before\nfor (let i = 0; i < 3; i++) { ... }\nthrow new Error(`[azure] ${method} ${path} failed after 3 retries`);\n\n// after\nfor (let i = 0; i < 5; i++) { ... /* honor retry-after when present */ }\nthrow new Error(`[azure] ${method} ${path} failed after 5 retries`);","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Stagger concurrent azure.mjs jobs sharing one subscription to avoid throttle exhaustion","Honor the retry-after header when present instead of fixed backoff","Make the whole pipeline re-runnable so exhausting retries is cheap"],"tags":["azure","retry","throttling","transient"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}