santifer/career-ops · error
⚠️ Could not save HTML: ${err.message}
Error message
⚠️ Could not save HTML: ${err.message} What it means
The outer try in openai-tailor.mjs failed — either the mkdirSync/existence check for output/, the writeFileSync of the tailored HTML, or the filename-building code threw — and the process exits with code 1. The tailored CV was NOT saved anywhere. Common fs codes: EACCES (output/ not writable), ENOSPC (disk full), ENOENT (a path component vanished mid-run). Unlike most warnings in this codebase, this one is terminal for the run.
Source
Thrown at openai-tailor.mjs:347
}
candidateName = candidateName
.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
const filename = `cv-${candidateName}-${companySlug}.html`;
const htmlPath = join(PATHS.output, filename);
writeFileSync(htmlPath, tailoredHtml, 'utf-8');
console.log(`\n✅ Tailored HTML saved: ${htmlPath}`);
// Print next steps
const pdfFilename = `cv-${candidateName}-${companySlug}-${roleSlug}-${new Date().toISOString().split('T')[0]}.pdf`;
const reportNumMatch = reportFilename.match(/^(\d+)-/);
const reportNum = reportNumMatch ? reportNumMatch[1] : '001';
console.log(`\n📄 Next step (generate PDF):\n node generate-pdf.mjs output/${filename} output/${pdfFilename} --format=letter --report=${reportNum}\n`);
} catch (err) {
console.warn(`⚠️ Could not save HTML: ${err.message}`);
process.exit(1);
}
View on GitHub (pinned to 60398d6549)
Solutions
- mkdir -p output && chmod u+w output, then re-run the tailor (the report it read still exists).
- Run df -h and free space if the error was ENOSPC.
- Verify output is a directory, not a stale file: ls -ld output.
- Treat the exit code 1 as 'nothing was written' — never assume partial output.
Example fix
// before
writeFileSync(htmlPath, tailoredHtml, 'utf-8');
} catch (err) {
console.warn(`⚠️ Could not save HTML: ${err.message}`);
process.exit(1);
}
// after — include path and code so the fatal exit is diagnosable
} catch (err) {
console.error(`Could not save HTML to ${htmlPath}: ${err.code ?? err.name} — check output/ permissions and disk space`);
process.exit(1);
} Defensive patterns
Strategy: validation
Validate before calling
import { mkdirSync, accessSync, constants } from 'node:fs';
mkdirSync('output', { recursive: true });
accessSync('output', constants.W_OK); // fail BEFORE any model call if the target dir cannot take the file Try / catch
catch (err) {
console.error(`Could not save HTML to ${htmlPath}: ${err.code ?? err.message}`);
process.exit(1);
} // exit non-zero so callers and CI know nothing was produced Prevention
- Pre-create and pre-check output/ writability at script start, before any API cost is incurred
- Run df -h before long CV-generation sessions
- Treat exit code 1 from the tailor as 'nothing was written' — never assume partial output
When it happens
Trigger: output/ is read-only or owned by another user (EACCES); disk full (ENOSPC); output/ deleted between the existence check and the write; PATHS.output pointing at an existing file rather than a directory.
Common situations: CI artifact cleanup racing the run; WSL/Docker permission mismatches; disk exhaustion after generating many CVs; a stray file named output blocking the directory.
Related errors
- ⚠️ Temporary HTML cleanup failed: ${err.message}
- ⚠️ Could not save report: ${err.message}
- ⚠️ Could not save report: ${err.message}
- ${label} escapes the tracker workspace: ${absPath}
- cannot read ${rel || '.'}: ${err.message}
AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20).
Data as JSON: /api/errors/3c886e885f549506.
Report an issue: GitHub.