{"record":{"id":"33e0844939f1a0c3","repo":"Hmbown/CodeWhale","slug":"too-many-redirects-while-downloading-url","errorCode":null,"errorMessage":"Too many redirects while downloading ${url}","messagePattern":"Too many redirects while downloading (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"npm/codewhale/scripts/verify-release-assets.js","lineNumber":108,"sourceCode":"    );\n    req.on(\"error\", reject);\n    req.end();\n  });\n}\n\nasync function verifyAsset(url, label) {\n  let status = await requestStatus(url, \"HEAD\");\n  if (status === 403 || status === 405) {\n    status = await requestStatus(url, \"GET\");\n  }\n  if (status < 200 || status >= 400) {\n    throw new Error(`${label} returned HTTP ${status} (${url})`);\n  }\n}\n\nasync function downloadText(url, redirects = 0) {\n  if (redirects > 10) {\n    throw new Error(`Too many redirects while downloading ${url}`);\n  }\n  const client = url.startsWith(\"https:\") ? https : http;\n  return new Promise((resolve, reject) => {\n    client\n      .get(\n        url,\n        {\n          headers: {\n            \"User-Agent\": \"codewhale-npm-release-check\",\n          },\n        },\n        (res) => {\n          const status = res.statusCode || 0;\n          if (status >= 300 && status < 400 && res.headers.location) {\n            const next = new URL(res.headers.location, url).toString();\n            res.resume();\n            resolve(downloadText(next, redirects + 1));\n            return;","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/npm/codewhale/scripts/verify-release-assets.js#L90-L126","documentation":"downloadText fetches text bodies (e.g. checksum files) following redirects with a depth counter. Exceeding 10 redirects aborts, since that indicates a redirect loop rather than a legitimate redirect chain.","triggerScenarios":"checksums() or bundleChecksums() → downloadText on a URL that redirects more than 10 times or loops (e.g. checksums file hosted behind a misconfigured mirror).","commonSituations":"Custom checksum file URL pointing at a looping proxy; CDN misconfiguration after release publish.","solutions":["Test the URL with curl -IL and fix the mirror/redirect configuration","Point at the official GitHub release download URL","Retry if transient CDN behavior"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const res = await fetch(url, { redirect: \"manual\" });\nlet hops = 0, loc = res.headers.get(\"location\");\nwhile (loc && hops < 10) { hops++; loc = (await fetch(loc, { redirect: \"manual\" })).headers.get(\"location\"); }\nif (hops > 10) throw new Error(`Redirect loop for ${url}`);","typeGuard":null,"tryCatchPattern":"try { text = await checksums(url); } catch (e) { if (/Too many redirects/.test(e.message)) { console.error(`Fix mirror redirect loop: ${url}`); throw e; } throw e; }","preventionTips":["Host checksums on the official release URL","Avoid chained mirrors","Log each redirect hop when debugging"],"tags":["http","redirect","network","checksums"],"backgroundTag":"http-error-response","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}