{"record":{"id":"9cac86be04d9eb0a","repo":"vercel/next.js","slug":"failed-to-fetch-url-too-many-retries","errorCode":null,"errorMessage":"Failed to fetch ${url}, too many retries","messagePattern":"Failed to fetch (.+?), too many retries","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bench/vercel/gen-request.js","lineNumber":13,"sourceCode":"import https from 'https'\nimport timer from '@szmarczak/http-timer'\n\n// a wrapper around genAsyncRequest that will retry the request 5 times if it fails\nexport async function genRetryableRequest(url) {\n  let retries = 0\n  while (retries < 10) {\n    try {\n      return await genAsyncRequest(url)\n    } catch (err) {}\n    retries++\n  }\n  throw new Error(`Failed to fetch ${url}, too many retries`)\n}\n\n// a wrapper around http.request that is enhanced with timing information\nasync function genAsyncRequest(url) {\n  return new Promise((resolve, reject) => {\n    const request = https.get(url)\n    timer(request)\n    request.on('response', (response) => {\n      let body = ''\n      response.on('data', (data) => {\n        body += data\n      })\n      response.on('end', () => {\n        if (response.statusCode !== 200) {\n          reject(new Error(`Failed to fetch ${url}`))\n        }\n        resolve({\n          ...response.timings.phases,","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/bench/vercel/gen-request.js#L1-L31","documentation":"Thrown by genRetryableRequest after 10 consecutive failed attempts to fetch a URL via genAsyncRequest. Each attempt can fail due to a network error, a non-200 status code, or a response error event. The wrapper swallows per-attempt errors and only surfaces this aggregate message once retries are exhausted, so no per-attempt detail is retained.","triggerScenarios":"The target deployment URL is unreachable (DNS, connection refused, TLS); the endpoint returns non-200 (404, 500, 502) for every attempt; the Vercel deployment is still cold/provisioning and timing out; rate limiting returns non-200 repeatedly.","commonSituations":"Benchmarking a Vercel deployment that is not yet ready; wrong/typo deployment URL; the deployment crashed (forceCrash mode); network egress blocked from the runner.","solutions":["curl the URL manually to see the actual status/body.","Wait for the deployment to finish provisioning and retry.","Verify the URL is correct and the deployment is healthy.","If intermittent, the 10-retry cap may be too low under heavy CI load — increase the retry count or add backoff."],"exampleFix":"// before: fixed 10 retries, no backoff\nwhile (retries < 10) { ... }\n\n// after: add delay between retries\nwhile (retries < 10) {\n  try { return await genAsyncRequest(url) } catch {}\n  await new Promise(r => setTimeout(r, 500 * retries))\n  retries++\n}","handlingStrategy":"retry","validationCode":"// Validate the URL is reachable before entering the retry loop\nasync function isReachable(url: string): Promise<boolean> {\n  try { const r = await fetch(url); return r.ok } catch { return false }\n}\nif (!(await isReachable(url))) {\n  throw new Error(`${url} is not reachable; check the deployment before retrying`)\n}","typeGuard":"null","tryCatchPattern":"try {\n  return await genRetryableRequest(url)\n} catch (e) {\n  // Inspect the deployment status; the message gives no per-attempt detail\n  throw new Error(`${(e as Error).message} — verify deployment is healthy: ${url}`)\n}","preventionTips":["Confirm the deployment URL is correct and healthy before benchmarking.","Add exponential backoff between retries to survive transient failures.","Increase the retry cap for flaky CI networks."],"tags":["network","retry","http","vercel"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}