{"record":{"id":"7f7c51c1e6663bc0","repo":"santifer/career-ops","slug":"temporary-html-cleanup-failed-err-message","errorCode":null,"errorMessage":"⚠️  Temporary HTML cleanup failed: ${err.message}","messagePattern":"⚠️  Temporary HTML cleanup failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"generate-pdf.mjs","lineNumber":1812,"sourceCode":"    // Close the page so a batch does not accumulate pages into the shared\n    // browser (leak → OOM). Optional-chained: the single path's browser.close()\n    // already reclaims the page, and minimal test doubles may omit close().\n    if (page && typeof page.close === 'function') {\n      await page.close().catch((err) => {\n        console.warn(`⚠️  Page cleanup failed: ${err.message}`);\n      });\n    }\n    // Close the per-document context too, so the JS-disabled context created\n    // above does not accumulate in the shared browser across a batch (#2384).\n    if (context && typeof context.close === 'function') {\n      await context.close().catch((err) => {\n        console.warn(`⚠️  Context cleanup failed: ${err.message}`);\n      });\n    }\n    // Clean up temp file\n    await unlink(tmpHtmlPath).catch((err) => {\n      if (err?.code !== 'ENOENT') {\n        console.warn(`⚠️  Temporary HTML cleanup failed: ${err.message}`);\n      }\n    });\n  }\n}\n\n/**\n * Render many already-normalized HTML documents through ONE shared Chromium.\n *\n * Maintainer conditions (#2384): the browser is launched once via the same\n * opts.launchBrowser seam the single path uses, and closed in a finally at the\n * batch boundary — it never outlives the batch and is torn down even if a\n * document throws. Each entry renders on its own page (renderInPage), and a\n * failing entry is captured as `{ok:false, error}` without stopping the rest.\n *\n * The browser is owned here: renderBatch closes whatever launchBrowser returns.\n * launchBrowser is a launch *factory*, not a caller-owned handle, so this does\n * not break test injection — the stub returns a fresh browser to be closed.\n *","sourceCodeStart":1794,"sourceCodeEnd":1830,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/generate-pdf.mjs#L1794-L1830","documentation":"Warning logged when deleting the temporary HTML file written for the render fails with any error other than ENOENT. The temp file (tmpHtmlPath) is page.setContent/page.goto input during rendering; a stale temp file is left behind on disk if this fires.","triggerScenarios":"fs unlink(tmpHtmlPath) rejects with a non-ENOENT code in the finally block — filesystem permission issue, temp file on a read-only or full volume, or the file locked/removed by another process (EBUSY/EPERM) while the renderer still held it open.","commonSituations":"Running with a read-only output/tmp directory (container with restricted mounts); disk quota exceeded; two generate-pdf runs in parallel using the same temp path; Windows file-locking in WSL setups.","solutions":["Ignore if rare — one stale temp file is harmless; delete it manually","Check permissions/ownership of the temp directory and run with write access","Ensure parallel runs do not share the same temp path","Free disk space if ENOSPC"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { accessSync, constants, statSync } from 'node:fs';\nfunction canUnlink(p) {\n  try { statSync(p); return constants.W_OK; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"await unlink(tmpHtmlPath).catch((err) => {\n  if (err?.code !== 'ENOENT') console.warn(`Temp cleanup failed: ${err.message}`);\n});","preventionTips":["Write temp files to os.tmpdir() with unique names (fs.mkdtemp) per run","Never share a temp path between concurrent runs","Ensure the temp directory is writable and has free space","Treat ENOENT on cleanup as success, as the code already does"],"tags":["filesystem","temp-file","cleanup","unlink"],"backgroundTag":"file-cleanup-failed","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"}