santifer/career-ops · warning
Warning: failed to append to status-log.tsv for #
Error message
Warning: failed to append to status-log.tsv for #${num}: ${err.message} What it means
Warning in reply-watch.mjs's main: after classifying replies and computing tracker status updates, the script appends each transition to data/status-log.tsv via fs.appendFileSync; if that append fails, the warning is logged per report number and processing continues. The tracker update itself still happens — only the historical ledger entry is lost.
Solutions
- Check err.message for the fs error code
- Ensure data/ exists and status-log.tsv is writable: mkdir -p data && touch data/status-log.tsv
- Fix disk/permission issues indicated by ENOSPC/EACCES
- Recovering the lost ledger rows: re-run the classification or append the transitions manually in {num}\t{date}\t{from}\t{to}\treply-watch\t form
Example fix
// before
try { fs.appendFileSync(statusLogFile, line, 'utf-8'); }
catch (err) { console.warn(`Warning: failed to append to status-log.tsv for #${num}: ${err.message}`); }
// after
fs.mkdirSync(dirname(statusLogFile), { recursive: true });
try { fs.appendFileSync(statusLogFile, line, 'utf-8'); }
catch (err) { console.warn(`Warning: failed to append to status-log.tsv for #${num}: ${err.message}`); } Defensive patterns
Strategy: try-catch
Validate before calling
import { mkdirSync, appendFileSync } from 'fs';
mkdirSync(dirname(statusLogFile), { recursive: true });
try { appendFileSync(statusLogFile, ''); } catch (e) { console.error('status-log.tsv not writable:', e.message); } Type guard
function isFsError(e) { return e instanceof Error && typeof e.code === 'string'; } Try / catch
try { fs.appendFileSync(statusLogFile, line, 'utf-8'); } catch (err) { console.warn(`Warning: failed to append for #${num}: ${err.message}`); /* tracker update already applied; log loss is non-fatal */ } Prevention
- Create data/status-log.tsv during onboarding/doctor runs
- Run pipeline scripts from the repo root
- Keep the ledger append-only and never chmod it read-only
- If a ledger row is lost, reconstruct it from tracker status history
When it happens
Trigger: appendFileSync to data/status-log.tsv fails: the file exists but is read-only, data/ is missing (no prior write created it), path is a directory, or disk is full (ENOSPC).
Common situations: Fresh checkout where data/status-log.tsv and sometimes data/ don't exist; running in a read-only CI workspace; disk quota exceeded.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- apify: JD cache write failed for
- ⚠️ Could not release report reservation
- ⚠️ Could not release report reservation
- ⚠️ Could not save HTML
- ⚠️ Could not save report
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/49fc81e781042275.
Report an issue: GitHub.
Appendix: source
Thrown at reply-watch.mjs:326
const count = r.count > 1 ? ` (${r.count} replies)` : '';
console.log(` #${r.num} ${r.company} (${r.role}): ${r.oldStatus} → ${r.newStatus}${count}`);
});
console.log('');
const answer = await askQuestion(`Apply recommended status updates to ${APPS_FILE}? (y/N): `);
if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
const statusLogFile = path.join(path.dirname(APPS_FILE), 'status-log.tsv');
const todayStr = localToday();
const result = await updateTrackerStatuses(updates, (applied, updatesByNum) => {
for (const num of applied) {
const u = updatesByNum.get(num);
if (u) {
const line = `${num}\t${todayStr}\t${u.oldStatus}\t${u.newStatus}\treply-watch\t\n`;
try {
fs.appendFileSync(statusLogFile, line, 'utf-8');
} catch (err) {
console.warn(`Warning: failed to append to status-log.tsv for #${num}: ${err.message}`);
}
}
}
});
for (const r of updates) {
const count = r.count > 1 ? ` (${r.count} replies)` : '';
if (result.applied.has(r.num)) {
console.log(`Updated #${r.num} to ${r.newStatus}${count}`);
} else if (result.alreadyCurrent.has(r.num)) {
console.log(`No change for #${r.num}: already ${r.newStatus}${count}`);
} else if (result.conflicts.has(r.num)) {
console.warn(`Skipped #${r.num}: status changed from ${r.oldStatus} to ${result.conflicts.get(r.num)} during review`);
} else if (result.missing.has(r.num)) {
console.warn(`Skipped #${r.num}: row no longer exists in the tracker`);
}
}
console.log('\n✅ Tracker review complete');
View on GitHub (pinned to aac998c7ed)