{"record":{"id":"3c886e885f549506","repo":"santifer/career-ops","slug":"could-not-save-html-err-message","errorCode":null,"errorMessage":"⚠️   Could not save HTML: ${err.message}","messagePattern":"⚠️   Could not save HTML: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"openai-tailor.mjs","lineNumber":349,"sourceCode":"  }\n  candidateName = candidateName\n    .toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');\n\n  const filename = `cv-${candidateName}-${companySlug}.html`;\n  const htmlPath = join(PATHS.output, filename);\n\n  writeFileSync(htmlPath, tailoredHtml, 'utf-8');\n  console.log(`\\n✅  Tailored HTML saved: ${htmlPath}`);\n\n  // Print next steps\n  const pdfFilename = `cv-${candidateName}-${companySlug}-${roleSlug}-${new Date().toISOString().split('T')[0]}.pdf`;\n  const reportNumMatch = reportFilename.match(/^(\\d+)-/);\n  const reportNum = reportNumMatch ? reportNumMatch[1] : '001';\n\n  console.log(`\\n📄  Next step (generate PDF):\\n    node generate-pdf.mjs output/${filename} output/${pdfFilename} --format=letter --report=${reportNum}\\n`);\n\n} catch (err) {\n  console.warn(`⚠️   Could not save HTML: ${err.message}`);\n  process.exit(1);\n}\n","sourceCodeStart":331,"sourceCodeEnd":352,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/openai-tailor.mjs#L331-L352","documentation":"Fatal-path warning in openai-tailor.mjs: the try block that generates and writes the tailored CV HTML to output/ failed, so the script logs err.message and calls process.exit(1). No HTML file is produced and the suggested generate-pdf.mjs next step cannot run.","triggerScenarios":"writeFileSync to output/{cv-*.html} fails: output/ directory missing, EACCES/EPERM on the file, ENOSPC, or the path derived from candidateName/companySlug is invalid.","commonSituations":"Fresh clone without output/ (gitignored and not auto-created); read-only CI workspace; disk full; extremely long company slug exceeding filename limits.","solutions":["Create the output directory: mkdir -p output","Check the err.message for EACCES/ENOSPC and fix permissions/disk space","Re-run the tailoring command after fixing","Ensure the company slug/name sanitized path is not excessively long"],"exampleFix":"// before\ncatch (err) {\n  console.warn(`⚠️   Could not save HTML: ${err.message}`);\n  process.exit(1);\n}\n// after\nmkdirSync(PATHS.output, { recursive: true }); // before the write, upstream of the catch","handlingStrategy":"validation","validationCode":"import { mkdirSync, accessSync, constants, statfsSync } from 'fs';\nmkdirSync(PATHS.output, { recursive: true });\naccessSync(PATHS.output, constants.W_OK);\nif (statfsSync(PATHS.output).bavail === 0) throw new Error('disk full');","typeGuard":"function isWritableDir(p) { try { accessSync(p, constants.W_OK); return statSync(p).isDirectory(); } catch { return false; } }","tryCatchPattern":"try { writeFileSync(htmlPath, html); } catch (err) { console.warn(`⚠️ Could not save HTML: ${err.message}`); process.exit(1); }","preventionTips":["Create output/ before generating CVs (it is gitignored and not auto-created)","Monitor disk usage on machines used for batch CV generation","Keep sanitized slugs short to avoid filesystem filename-length limits"],"tags":["nodejs","filesystem","cv-generation"],"backgroundTag":"file-write-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"}