{"record":{"id":"a0484284f2d983df","repo":"itwanger/toBeBetterJavaer","slug":"downloaded-file-is-empty","errorCode":null,"errorMessage":"Downloaded file is empty","messagePattern":"Downloaded file is empty","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/convert-mdnice-images-to-cdn.js","lineNumber":373,"sourceCode":"}\n\nasync function downloadImage(url) {\n  const response = await fetch(url, {\n    redirect: \"follow\",\n    headers: {\n      \"User-Agent\": \"toBeBetterJavaer-image-cdn/1.0\",\n    },\n  });\n  if (!response.ok) {\n    throw new Error(`Download failed with HTTP ${response.status}`);\n  }\n  const contentType = normalizeContentType(response.headers.get(\"content-type\"));\n  if (contentType && !contentType.startsWith(\"image/\") && contentType !== \"application/octet-stream\") {\n    throw new Error(`Unexpected content type: ${contentType}`);\n  }\n  const body = Buffer.from(await response.arrayBuffer());\n  if (body.length === 0) {\n    throw new Error(\"Downloaded file is empty\");\n  }\n  return { body, contentType };\n}\n\nfunction normalizeContentType(contentType) {\n  if (!contentType) {\n    return \"\";\n  }\n  return contentType.split(\";\")[0].trim().toLowerCase();\n}\n\nfunction contentTypeForPath(filePath) {\n  const extension = path.extname(filePath).toLowerCase();\n  switch (extension) {\n    case \".png\":\n      return \"image/png\";\n    case \".jpg\":\n    case \".jpeg\":","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/itwanger/toBeBetterJavaer/blob/6617f5fd0b0597735bdc028f2fcd036817877327/scripts/convert-mdnice-images-to-cdn.js#L355-L391","documentation":"Thrown by downloadImage() in scripts/convert-mdnice-images-to-cdn.js when the response body, after being buffered into a Buffer, has zero bytes. A 2xx response with an image Content-Type but an empty body means nothing would be uploaded, so the script refuses before touching OSS.","triggerScenarios":"Source server returns 200 with correct Content-Type and zero-length body (truncated upload on the origin, a bad proxy response, or a redirect chain that terminates in an empty stream). Requires --write mode since dry runs never download.","commonSituations":"Flaky upstream CDNs; interrupted origin uploads; middleboxes (corporate proxies, VPNs) returning empty bodies; rare but real on mobile hotspots.","solutions":["Rerun the command — empty bodies from transient network faults usually resolve on retry","Verify manually: `curl -o /tmp/x.png <url> && ls -l /tmp/x.png` to confirm the source serves bytes","If the source is permanently empty, replace the image reference with a working copy of the asset"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const res = await fetch(url, { headers: { \"User-Agent\": \"toBeBetterJavaer-image-cdn/1.0\" } });\nconst len = Number(res.headers.get(\"content-length\") || \"-1\");\nif (len === 0) console.warn(`Source serves an empty body: ${url}`);","typeGuard":null,"tryCatchPattern":"catch (err) { if (err.message === \"Downloaded file is empty\") { await sleep(backoff); return retryOnce(); } throw err; }","preventionTips":["Retry the full run once before investigating — empty bodies are usually transient","Verify suspicious sources with curl -o and ls -l","Run conversions on a stable network"],"tags":["network","download","validation"],"backgroundTag":null,"analyzedSha":"6617f5fd0b0597735bdc028f2fcd036817877327","analyzedAt":"2026-08-14T14:50:55.107Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}