{"record":{"id":"021e70a930e776d1","repo":"koala73/worldmonitor","slug":"jodi-gas-zip-fetch-failed-http-resp-status","errorCode":null,"errorMessage":"JODI Gas ZIP fetch failed: HTTP ${resp.status}","messagePattern":"JODI Gas ZIP fetch failed: HTTP (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/seed-jodi-gas.mjs","lineNumber":292,"sourceCode":"}\n\nasync function fetchAndParseCsv() {\n  // Discovery and archive download share the existing total request budget.\n  const signal = AbortSignal.timeout(120_000);\n  const catalogResponse = await fetch(CATALOG_URL, {\n    headers: { 'User-Agent': CHROME_UA },\n    signal,\n    redirect: 'error',\n  });\n  if (!catalogResponse.ok) throw new Error(`JODI Gas catalog fetch failed: HTTP ${catalogResponse.status}`);\n  const zipUrl = resolveGasArchiveUrl(await catalogResponse.json());\n  console.log(`  Fetching JODI Gas ZIP from ${zipUrl}`);\n  const resp = await fetch(zipUrl, {\n    headers: { 'User-Agent': CHROME_UA, 'Accept-Encoding': 'identity' },\n    signal,\n    redirect: 'error',\n  });\n  if (!resp.ok) throw new Error(`JODI Gas ZIP fetch failed: HTTP ${resp.status}`);\n\n  const arrayBuf = await resp.arrayBuffer();\n  const zipBuf = Buffer.from(arrayBuf);\n  console.log(`  ZIP downloaded: ${(zipBuf.length / 1024 / 1024).toFixed(1)} MB`);\n\n  const entry = findZipEntry(zipBuf, CSV_FILENAME);\n  if (!entry) throw new Error(`Could not find ${CSV_FILENAME} in ZIP`);\n  console.log(`  Found entry: ${entry.entryName} (compression=${entry.compression})`);\n\n  const compressed = zipBuf.slice(entry.dataOffset, entry.dataOffset + entry.compSize);\n  let csvBuf;\n  if (entry.compression === 0) {\n    csvBuf = compressed;\n  } else if (entry.compression === 8) {\n    csvBuf = await inflateRawAsync(compressed);\n  } else {\n    throw new Error(`Unsupported ZIP compression method: ${entry.compression}`);\n  }","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/koala73/worldmonitor/blob/e586b8b4b80f595aa7ece295eec10d76f2921240/scripts/seed-jodi-gas.mjs#L274-L310","documentation":"Thrown by fetchAndParseCsv in the JODI Gas seeder when the HTTP response for the JODI Gas ZIP archive has a non-ok status. The script downloads the monthly JODI Gas world ZIP and unblocks it locally, so any 4xx/5xx from the host aborts the seed. redirect:'error' also means redirect responses surface as failures here.","triggerScenarios":"fetch(zipUrl) returns resp.ok === false, i.e. any HTTP 4xx/5xx status on the JODI Gas ZIP URL (e.g. 404 after the archive path changed, 403 from bot blocking, 5xx from the host).","commonSituations":"JODI renames or moves the monthly ZIP so the hardcoded URL 404s; CDN/WAF blocks the request despite the Chrome User-Agent; the JODI site is down for maintenance returning 5xx; an offline/proxied CI environment intercepts the request.","solutions":["Open the JODI Gas website and confirm the current ZIP URL; update zipUrl in scripts/seed-jodi-gas.mjs if the path changed.","Retry later if the status is 5xx or 429 — the host is temporarily unavailable or rate limiting.","Check network/proxy configuration and whether the environment allows outbound HTTPS to the JODI host.","Verify the request headers (User-Agent) are not being rejected; test the URL in a browser or with curl -I."],"exampleFix":"// before\nif (!resp.ok) throw new Error(`JODI Gas ZIP fetch failed: HTTP ${resp.status}`);\n// after\nif (!resp.ok) {\n  if (resp.status === 404) console.warn('JODI ZIP URL may be stale; check current archive path');\n  throw new Error(`JODI Gas ZIP fetch failed: HTTP ${resp.status}`);\n}","handlingStrategy":"retry","validationCode":"const head = await fetch(zipUrl, { method: 'HEAD' }); if (!head.ok) console.warn(`JODI ZIP URL unhealthy: HTTP ${head.status}`);","typeGuard":null,"tryCatchPattern":"try { const zip = await fetchAndParseCsv(zipUrl, signal); } catch (e) { if (/HTTP \\d{3}/.test(e.message)) { console.error('JODI host returned an error status; check URL freshness or retry later', e.message); } throw e; }","preventionTips":["Pin and periodically re-verify the JODI ZIP URL with a HEAD check in CI","Add exponential backoff retries for 5xx/429 statuses","Keep the browser-like User-Agent header to avoid bot blocking","Alert on repeated 404s, which indicate the archive path moved"],"tags":["network","http","seed-script","upstream-api"],"backgroundTag":"http-error-response","analyzedSha":"e586b8b4b80f595aa7ece295eec10d76f2921240","analyzedAt":"2026-09-22T01:50:49.965Z","contentChangedAt":"2026-09-22T01:50:49.965Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}