{"record":{"id":"7dc81207805e47f5","repo":"santifer/career-ops","slug":"image-failed-to-decode-within-10s-unreadable-or-c","errorCode":null,"errorMessage":"Image failed to decode within 10s (unreadable or corrupt file?): ${inputPath}","messagePattern":"Image failed to decode within 10s \\(unreadable or corrupt file\\?\\): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"img-to-pdf.mjs","lineNumber":140,"sourceCode":"<body>\n<img id=\"career-ops-img\" src=\"data:${mimeType};base64,${base64}\">\n</body>\n</html>`;\n\n  await mkdir(dirname(outputPath), { recursive: true });\n\n  const browser = await chromium.launch({ headless: true });\n  try {\n    const page = await browser.newPage();\n    await page.setContent(html, { waitUntil: 'load' });\n\n    try {\n      await page.waitForFunction(() => {\n        const img = document.getElementById('career-ops-img');\n        return !!img && img.complete && img.naturalWidth > 0 && img.naturalHeight > 0;\n      }, { timeout: 10000 });\n    } catch (err) {\n      throw new Error(`Image failed to decode within 10s (unreadable or corrupt file?): ${inputPath}`);\n    }\n\n    const { width, height } = await page.evaluate(() => {\n      const img = document.getElementById('career-ops-img');\n      return { width: img.naturalWidth, height: img.naturalHeight };\n    });\n\n    // 96 CSS px per inch is the standard browser/Playwright conversion —\n    // sizing the PDF page to the image's own dimensions means the image\n    // fills the page exactly: no cropping, no blank margins.\n    const widthIn = width / 96;\n    const heightIn = height / 96;\n\n    const pdfBuffer = await page.pdf({\n      width: `${widthIn}in`,\n      height: `${heightIn}in`,\n      margin: { top: '0', right: '0', bottom: '0', left: '0' },\n      printBackground: true,","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/img-to-pdf.mjs#L122-L158","documentation":"Thrown by convertImageToPdf() in img-to-pdf.mjs when the in-page <img> did not reach naturalWidth>0 && naturalHeight>0 && complete within a 10-second Playwright waitForFunction. This means Chromium could load the HTML shell but the embedded base64 image never decoded — almost always a corrupt, truncated, or zero-byte source file rather than a slow network (the image is inline base64, so there is no network).","triggerScenarios":"The source file is truncated (download interrupted), zero-byte, a valid extension but wrong contents (e.g. a .png that is actually HTML), or a degenerate image Chromium's decoder rejects. waitForFunction times out at 10000ms and the catch rethrows this message.","commonSituations":"Partially downloaded image; a file renamed from another format; an SVG with invalid XML that Chromium cannot rasterize; a corrupt BMP/GIF; disk read returned short.","solutions":["Open the source image in a normal viewer to confirm it decodes — if it doesn't, re-download or re-export the original.","Check the file is not zero-byte: `ls -l input.png` and `file input.png` to confirm type matches extension.","For SVGs, validate the XML: `xmllint --noout input.svg`.","Re-export from the source application (Photoshop/Figma/etc.) to a fresh PNG/JPEG."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-validate the file is non-empty and decodable-ish before Chromium\nconst stat = await fsPromises.stat(inputPath);\nif (stat.size === 0) throw new Error('Image file is zero bytes: ' + inputPath);","typeGuard":null,"tryCatchPattern":"try {\n  return await convertImageToPdf(inputPath, outputPath);\n} catch (e) {\n  if (e.message.includes('failed to decode within 10s')) {\n    // almost always corrupt/truncated source; re-export from original\n    throw new Error(`Image appears corrupt: ${inputPath}. Re-export the original as PNG/JPEG.`);\n  }\n  throw e;\n}","preventionTips":["Confirm the source image opens in a viewer before piping it through the converter.","Check file size > 0 and `file` output matches extension as a cheap pre-check.","Validate SVGs with xmllint before conversion.","Re-export from the source app if a file is suspect."],"tags":["image","pdf","playwright","timeout","corrupt-file"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}