{"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/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/img-to-pdf.mjs#L122-L158","documentation":"After loading the image into a headless Chromium page, convertImageToPdf() waits up to 10 seconds for the <img> to fully decode (img.complete with naturalWidth/naturalHeight > 0). If the wait times out, the file is presumed unreadable or corrupt and this error replaces the generic timeout.","triggerScenarios":"convertImageToPdf() given a corrupt/truncated image file, a zero-byte file, a file whose bytes do not match its extension, or a path pointing at something that loads but never decodes (e.g. an HTML file named .png).","commonSituations":"Interrupted downloads producing truncated files; images with wrong extensions; files locked or still being written by another process during conversion.","solutions":["Open the image in a viewer to confirm it is not corrupt; re-export or re-download it if broken.","Verify the file size is > 0 and that the bytes match the extension (`file image.png`).","Convert/re-encode the image with an image tool (`magick input output.png`) to normalize it, then retry."],"exampleFix":"// before\nawait convertImageToPdf('truncated.png', 'out.pdf');\n// after (guard first)\nimport { statSync } from 'node:fs';\nif (statSync('fixed.png').size === 0) throw new Error('empty image');\nawait convertImageToPdf('fixed.png', 'out.pdf');","handlingStrategy":"try-catch","validationCode":"import { statSync } from 'node:fs';\nimport { readFileSync } from 'node:fs';\nconst buf = readFileSync(p);\nif (buf.length < 8 || !buf.subarray(0, 8).toString('hex').match(/^(89504e47|ffd8ff|47494638|52494646)/)) {\n  throw new Error(`${p} does not look like a valid image`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await convertImageToPdf(input, output);\n} catch (err) {\n  if (err.message.includes('failed to decode')) {\n    console.error(`Image ${input} is corrupt or unreadable; re-export it and retry.`);\n  } else throw err;\n}","preventionTips":["Sanity-check image magic bytes and file size before conversion.","Re-encode suspicious images with an image tool before batching.","Don't convert files still being written by another process."],"tags":["image","pdf","decode","timeout","playwright"],"backgroundTag":"request-timeout","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}