{"record":{"id":"34bd01f3a554f486","repo":"santifer/career-ops","slug":"could-not-determine-the-rendered-pdf-page-count-fr","errorCode":null,"errorMessage":"Could not determine the rendered PDF page count from its page tree.","messagePattern":"Could not determine the rendered PDF page count from its page tree\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"generate-pdf.mjs","lineNumber":336,"sourceCode":"  const objects = new Map();\n  const objectPattern = /(?:^|[\\r\\n])(\\d+)\\s+(\\d+)\\s+obj\\b([\\s\\S]*?)\\bendobj\\b/g;\n\n  for (const match of pdf.matchAll(objectPattern)) {\n    const streamIndex = match[3].search(/\\bstream(?:\\r?\\n|\\r)/);\n    const dictionary = streamIndex === -1 ? match[3] : match[3].slice(0, streamIndex);\n    objects.set(`${match[1]} ${match[2]}`, dictionary);\n  }\n\n  const catalog = [...objects.values()].find((body) => /\\/Type\\s*\\/Catalog\\b/.test(body));\n  const pagesRef = catalog?.match(/\\/Pages\\s+(\\d+)\\s+(\\d+)\\s+R\\b/);\n  const pages = pagesRef ? objects.get(`${pagesRef[1]} ${pagesRef[2]}`) : null;\n  const count = pages && /\\/Type\\s*\\/Pages\\b/.test(pages)\n    ? pages.match(/\\/Count\\s+(\\d+)\\b/)\n    : null;\n  const pageCount = count ? Number(count[1]) : 0;\n\n  if (!Number.isInteger(pageCount) || pageCount < 1) {\n    throw new Error('Could not determine the rendered PDF page count from its page tree.');\n  }\n  return pageCount;\n}\n\n/**\n * Convert a path to a repo-relative manifest entry, or blank if it is unknown\n * or outside the career-ops repository.\n *\n * @param {string} pathValue - Absolute or cwd-relative filesystem path.\n * @returns {string} Repo-relative path using forward slashes, or an empty string.\n */\nexport function repoRelativeManifestPath(pathValue) {\n  if (!pathValue) return '';\n  const rel = relative(__dirname, resolve(pathValue));\n  if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) return '';\n  return rel.split(sep).join('/');\n}\n","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/generate-pdf.mjs#L318-L354","documentation":"Thrown by readPageCount() in generate-pdf.mjs when it cannot find a valid /Pages dictionary with a /Count entry in the PDF catalog. The parser walks PDF indirect objects, locates the /Type /Catalog root, follows its /Pages reference, and reads /Count; if any link is missing or the structure is malformed, it refuses to guess. This is a defensive parse against mistaking page-like text in content streams for real page objects.","triggerScenarios":"Chromium returned an empty, truncated, or non-conformant PDF buffer (e.g. browser crashed mid-write, disk full, pipe closed early); the PDF has an unusual xref/object structure the regex-based parser cannot traverse; a non-PDF file (HTML error page) was captured into the buffer path.","commonSituations":"Playwright/Chromium process killed by OOM or timeout during PDF write; writing to a network mount that truncated output; concurrent PDF generation corrupting a temp file; Chromium version change emitting a catalog structure the parser doesn't recognize.","solutions":["Check that Chromium completed without error — inspect the launch log and the buffer length before calling readPageCount.","Re-run the PDF generation in isolation to rule out a transient crash/resource issue.","If the PDF looks valid in a viewer but still fails, the parser regex may need updating for a new Chromium output format; file a bug with the buffer's first ~2KB.","Verify the output path is a real local file and not a truncated stream."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate the buffer looks like a PDF before parsing page count\nfunction looksLikePdf(buf) {\n  return buf && buf.length > 0 && buf.slice(0, 5).toString('ascii') === '%PDF-';\n}\nif (!looksLikePdf(buffer)) {\n  throw new Error('Chromium did not produce a valid PDF buffer.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const pageCount = readPageCount(buffer);\n  enforcePageBudget(pageCount, opts);\n} catch (e) {\n  if (e.message.includes('page tree')) {\n    // log buffer length + first bytes for diagnosis, retry the render\n    console.error('PDF parse failed; buffer bytes:', buffer.length);\n  }\n  throw e;\n}","preventionTips":["Ensure Chromium fully exits before reading the PDF buffer (await the render promise).","Write PDFs to local disk, not network mounts that can truncate.","Avoid concurrent writes to the same temp path.","Log buffer length when this fires — a tiny/zero length points to a Chromium crash."],"tags":["pdf","parsing","playwright","chromium","io"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}