santifer/career-ops · warning

Skipped # : row no longer exists in the tracker

Error message

Skipped #${r.num}: row no longer exists in the tracker

What it means

During the apply phase, reply-watch verifies the target row still exists before updating. If #N is absent from the tracker (deleted, merged away by dedup/merge-tracker, or archived via outcome), the update is skipped and this warning reports it, with the run continuing to the remaining rows.

Solutions

  1. Check what happened to the row: if it was merged into another #, apply the status to the surviving row with `node set-status.mjs <surviving#> <State>`.
  2. If the application was archived via outcome.mjs, no update is needed — the replies are historical.
  3. Verify CAREER_OPS_TRACKER / the tracker path matches the one the replies were classified against.
  4. Clean stale entries from data/reply-candidates.json if the # will never exist again.

Example fix

// before
// Skipped #57: row no longer exists in the tracker (row was deduped into #52)
// after
node set-status.mjs 52 Interview --note "status from merged row 57"
Defensive patterns

Strategy: validation

Validate before calling

const exists = trackerRows.some(row => row.num === r.num);
if (!exists) console.warn(`#${r.num} gone from tracker — skip or re-point at merged row`);

Try / catch

} else if (result.missing.has(r.num)) {
  console.warn(`Skipped #${r.num}: row no longer exists in the tracker`);
  // find surviving row (dedup/outcome) and update that instead
}

Prevention

When it happens

Trigger: A reply-candidates.json entry references tracker #N, but by apply time the row was removed — outcome.mjs archived it, merge-tracker deduped it into another row, the tracker was rebuilt, or the # referenced a row from a different tracker file.

Common situations: Recording an outcome for an application that had pending replies; running dedup-tracker between classification and apply; pointing CAREER_OPS_TRACKER at a different/older tracker file than when replies were captured.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/e910f0fabd41f362. Report an issue: GitHub.

Appendix: source

Thrown at reply-watch.mjs:340

            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');

      // Sync tracker DB if tracker.mjs exists
      try {
        const { execSync } = await import('child_process');
        execSync('node tracker.mjs sync', { stdio: 'ignore' });
        console.log('Synced database index (applications.db).');
      } catch (e) {
        // ignore
      }
    } else {
      console.log('Updates skipped.');
    }
  }
}

View on GitHub (pinned to aac998c7ed)