{"record":{"id":"b533e90bafcff6a6","repo":"oven-sh/bun","slug":"azure-operation-poll-failed-after-fetcherrors","errorCode":null,"errorMessage":"[azure] Operation poll failed after ${fetchErrors} fetch errors","messagePattern":"\\[azure\\] Operation poll failed after (.+?) fetch errors","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/azure.mjs","lineNumber":161,"sourceCode":"  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 });\n      }\n      console.warn(`[azure] Operation poll fetch error (${fetchErrors}), retrying...`);\n      await new Promise(r => setTimeout(r, 10_000));\n      continue;\n    }\n\n    if (!response.ok) {\n      throw new Error(`[azure] Operation poll failed: ${response.status} ${await response.text()}`);\n    }\n\n    const data = await response.json();\n\n    if (data.status === \"Succeeded\") {\n      return data.properties?.output ?? data;\n    }\n    if (data.status === \"Failed\" || data.status === \"Canceled\") {\n      throw new Error(`[azure] Operation ${data.status}: ${data.error?.message ?? \"unknown\"}`);\n    }","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/azure.mjs#L143-L179","documentation":"While polling an Azure long-running operation URL, the raw fetch itself (network layer) threw more than 10 times, with a 10-second pause between tries. The original network error is attached as { cause }. This is a connectivity/DNS/egress failure sustained over ~100 seconds, not an Azure API rejection.","triggerScenarios":"CI runner lost network egress; DNS resolution broken; a proxy/firewall drops connections to management.azure.com; TLS interception failing intermittently.","commonSituations":"Self-hosted runner behind a corporate proxy; transient VPC/network policy change mid-build; DNS outage in the CI cloud.","solutions":["Check the cause in the error/stack — ECONNRESET, ENOTFOUND, ETIMEDOUT each point differently","Verify egress to the operation URL host from the runner (curl it)","Fix proxy/DNS config on the runner and retry the job","Re-run once network is restored; the operation may still complete server-side"],"exampleFix":"// before\ncatch (err) {\n  fetchErrors++;\n  if (fetchErrors > 10) throw new Error(`[azure] Operation poll failed after ${fetchErrors} fetch errors`, { cause: err });\n}\n\n// after\ncatch (err) {\n  fetchErrors++;\n  console.error(`poll network error ${fetchErrors}:`, err.code ?? err.message);\n  if (fetchErrors > 10) throw new Error(`[azure] Operation poll failed after ${fetchErrors} fetch errors`, { cause: err });\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check runner egress/DNS to management.azure.com before long operations","Inspect err.code (ENOTFOUND/ECONNRESET/ETIMEDOUT) in the cause to pick the right fix","Design jobs to be resumable since the operation may complete server-side during the outage"],"tags":["azure","network","transient","polling"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}