{"record":{"id":"8856f115a2e6060d","repo":"CloakHQ/CloakBrowser","slug":"http-response-status","errorCode":null,"errorMessage":"HTTP ${response.status}","messagePattern":"HTTP \\$\\{response\\.status\\}","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"js/src/geoip.ts","lineNumber":380,"sourceCode":"    // Another concurrent launch may have owned the download; reuse its result.\n    return fs.existsSync(dbPath) ? dbPath : null;\n  } catch {\n    return null;\n  }\n}\n\nasync function downloadGeoipDb(dest: string): Promise<void> {\n  const dir = path.dirname(dest);\n  fs.mkdirSync(dir, { recursive: true });\n  console.log(\"[cloakbrowser] Downloading GeoIP database (~70 MB)…\");\n\n  const tmpPath = `${dest}.tmp.${Date.now()}`;\n  try {\n    const response = await fetch(GEOIP_DB_URL, {\n      redirect: \"follow\",\n    });\n    if (!response.ok || !response.body) {\n      throw new Error(`HTTP ${response.status}`);\n    }\n\n    const fileStream = createWriteStream(tmpPath);\n    const reader = response.body.getReader();\n\n    for (;;) {\n      const { done, value } = await reader.read();\n      if (done) break;\n      fileStream.write(value);\n    }\n\n    await new Promise<void>((resolve, reject) => {\n      fileStream.end(() => resolve());\n      fileStream.on(\"error\", reject);\n    });\n\n    fs.renameSync(tmpPath, dest);\n    console.log(`[cloakbrowser] GeoIP database ready: ${dest}`);","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/js/src/geoip.ts#L362-L398","documentation":"downloadGeoipDb received a non-2xx HTTP status (or no body) when fetching the GeoIP database URL, and throws `HTTP <status>` to abort the download before writing a bad file.","triggerScenarios":"The fetch to GEOIP_DB_URL returns 403/404/429/5xx, or response.body is null (e.g. a redirect chain ending without a body despite redirect: 'follow').","commonSituations":"Rate-limited or expired CDN links, license-key-protected MaxMind endpoints without credentials, corporate proxies returning 407, or transient 5xx outages at the mirror.","solutions":["Retry the download after a delay (429/5xx are often transient) with backoff","Check the GEOIP_DB_URL constant/endpooint is still valid and licensed (MaxMind requires account/license keys for GeoLite2)","Bypass or configure corporate proxy env vars (HTTPS_PROXY) if a 407/403 intercept page is returned","Vendor or manually place the .mmdb file and skip runtime download"],"exampleFix":"// before\nawait downloadGeoipDb(dest);\n\n// after\nfor (let attempt = 1; attempt <= 3; attempt++) {\n  try { await downloadGeoipDb(dest); break; }\n  catch (e) {\n    if (attempt === 3) throw e;\n    await sleep(attempt * 2000);\n  }\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"function isHttpDownloadError(e: unknown): e is Error {\n  return e instanceof Error && /^HTTP \\d{3}$/.test(e.message);\n}","tryCatchPattern":"for (let a = 1; a <= 3; a++) {\n  try { await downloadGeoipDb(dest); break; }\n  catch (e) {\n    if (a === 3 || !isHttpDownloadError(e)) throw e;\n    await new Promise(r => setTimeout(r, a * 2000));\n  }\n}","preventionTips":["Wrap downloads in exponential-backoff retry (429/5xx are transient)","Cache the DB so downloads are rare; vendor it in Docker images","Keep the download URL/license credentials current","Monitor download failures at startup and degrade gracefully"],"tags":["geoip","http","download","rate-limit"],"backgroundTag":"http-download-failed-status","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}