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

  1. Check err.message for the fs error code
  2. Ensure data/ exists and status-log.tsv is writable: mkdir -p data && touch data/status-log.tsv
  3. Fix disk/permission issues indicated by ENOSPC/EACCES
  4. 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

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


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)