santifer/career-ops · warning
⚠️ Could not save report: ${err.message}
Error message
⚠️ Could not save report: ${err.message} What it means
Best-effort warning in gemini-eval.mjs's report-save phase: writing the report file to reports/ or the tracker-addition TSV to batch/tracker-additions/ failed, so evaluation output is not persisted and exitCode is set to 1. The original filesystem error (EACCES, ENOENT directory missing, invalid filename characters from the company slug, disk full) is appended to the message.
Source
Thrown at gemini-eval.mjs:441
writeFileSync(reportPath, reportContent, 'utf-8');
mkdirSync(PATHS.trackerAdditions, { recursive: true });
const trackerFields = [
String(parseInt(num, 10)),
today,
tsvSafe(company),
tsvSafe(role),
'Evaluated',
normalizedTrackerScore(score),
'❌',
`[${num}](reports/${filename})`,
'Gemini evaluation',
];
writeFileSync(trackerPath, `${trackerFields.join('\t')}\n`, 'utf-8');
console.log(`\n✅ Report saved: reports/${filename}`);
console.log(`📊 Tracker addition saved: batch/tracker-additions/${num}-${companySlug}.tsv`);
reportSaved = true;
} catch (err) {
console.warn(`⚠️ Could not save report: ${err.message}`);
process.exitCode = 1;
}
if (reportSaved) {
try {
const mergeOutput = execFileSync(process.execPath, [join(ROOT, 'merge-tracker.mjs')], {
cwd: ROOT,
encoding: 'utf-8',
stdio: ['ignore', 'pipe', 'pipe'],
});
if (mergeOutput.trim()) console.log(mergeOutput.trim());
console.log('📊 Tracker merged into data/applications.md.');
} catch (err) {
console.warn(`⚠️ Report saved, but could not merge tracker addition into data/applications.md: ${err.message}`);
process.exitCode = 1;
}
}
} finally {View on GitHub (pinned to 60398d6549)
Solutions
- Create the missing directories: `mkdir -p reports batch/tracker-additions`
- Check the appended errno in the message — EACCES means fix permissions, ENOSPC means free space
- Re-run the evaluation (the reservation is released in finally, so the report number is not leaked)
- If the company name is the problem, sanitize or manually add the entry per the tracker TSV conventions
Example fix
# before node gemini-eval.mjs "<jd>" # reports/ absent -> Could not save report: ENOENT # after mkdir -p reports batch/tracker-additions && node gemini-eval.mjs "<jd>"
Defensive patterns
Strategy: try-catch
Validate before calling
import { accessSync, constants, mkdirSync } from 'node:fs';
for (const dir of ['reports', 'batch/tracker-additions']) {
mkdirSync(dir, { recursive: true });
accessSync(dir, constants.W_OK); // throws early with a clear EACCES instead of mid-eval
} Try / catch
try {
saveReport();
} catch (err) {
if (['ENOENT', 'EACCES', 'ENOSPC'].includes(err.code)) {
// report did not persist: fix fs issue, re-run evaluation; reservation is released in finally
console.error(`report not saved (${err.code}); safe to re-run`);
process.exitCode = 1;
} else {
throw err;
}
} Prevention
- Pre-create reports/ and batch/tracker-additions/ in setup scripts and CI
- Run as a user with write access to the repo; watch disk space in containers
- Treat exitCode 1 after this warning as 'not persisted' and always re-run rather than assuming success
When it happens
Trigger: Running gemini-eval when reports/ or batch/tracker-additions/ does not exist or is read-only; a company name whose slug produces an illegal filename on the filesystem; ENOSPC. The catch keeps going to the finally block that releases reserved report numbers.
Common situations: Fresh or partial clones missing gitignored output dirs; running as a user without write permission to the repo; exotic characters (slashes, colons on Windows) in the scraped company name; full disks in containers.
Related errors
- Invalid or blocked URL: ${rejected.reason}
- cannot read ${rel || '.'}: ${err.message}
- refusing to hash symlink: ${childRel}
- refusing to hash non-regular file: ${childRel}
- ⚠️ Could not save report: ${err.message}
AI-assisted analysis of santifer/career-ops@60398d6549 (2026-08-20).
Data as JSON: /api/errors/78e262ecf818177f.
Report an issue: GitHub.