santifer/career-ops · error · SeedError

ROW_NOT_FOUND

ROW_NOT_FOUND

Error message

Tracker not found at ${trackerPath}

What it means

seedFollowup resolves the tracker path (options.trackerPath > CAREER_OPS_TRACKER env > data/applications.md > root applications.md) and throws ROW_NOT_FOUND if that file does not exist on disk. The tracker is the source of truth for application rows — without it, no row can be found or seeded.

Source

Thrown at followup-seed.mjs:425

 * @param {string} [options.lockDir]
 * @param {number} [options.lockTimeoutMs]
 * @param {number} [options.lockRetryMs]
 * @param {number} [options.lockStaleMs]
 * @returns {Promise<object>}
 */
export async function seedFollowup(appNum, options = {}) {
  if (!Number.isInteger(appNum) || appNum <= 0) {
    throw new SeedError('USAGE', `Invalid appNum: ${appNum}`);
  }
  if (options.date != null && !isValidCalendarDate(options.date)) {
    throw new SeedError('INVALID_DATE', `--date must be a real calendar date in YYYY-MM-DD form: ${options.date}`);
  }

  const trackerPath = resolveTrackerPath(options.trackerPath);
  const followupsPath = resolveFollowupsPath(options.followupsPath);

  if (!existsSync(trackerPath)) {
    throw new SeedError('ROW_NOT_FOUND', `Tracker not found at ${trackerPath}`);
  }
  const rows = readTrackerRows(trackerPath);
  const row = rows.find(r => r.num === appNum);
  if (!row) {
    throw new SeedError('ROW_NOT_FOUND', `Application #${appNum} not found in ${trackerPath}`);
  }

  const normalized = normalizeStatus(row.status);
  if (normalized !== 'applied' && !options.force) {
    throw new SeedError('NOT_APPLIED', `Application #${appNum} is not Applied (status: "${row.status.trim()}"); use --force to seed anyway`);
  }

  const appliedDate = resolveAppliedDate(row, options.date);
  const cadence = resolveCadenceConfig({ profilePath: options.profilePath });
  const nextDate = addDays(parseDate(appliedDate), cadence.applied_first);
  const setDate = todayStr();
  const pin = formatPinLine(appNum, nextDate, setDate);

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Run node doctor.mjs --json to confirm whether onboarding is needed.
  2. Verify data/applications.md exists; if not, create it with the tracker header (see AGENTS.md Step 4).
  3. Check CAREER_OPS_TRACKER env var: echo $CAREER_OPS_TRACKER and ensure it resolves to a real file.
  4. Ensure the process working directory is the career-ops repo root.
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'fs';

const trackerPath = options.trackerPath
  || process.env.CAREER_OPS_TRACKER
  || 'data/applications.md';
if (!existsSync(trackerPath)) {
  throw new Error(`Tracker not found at ${trackerPath}. Run onboarding first.`);
}
await seedFollowup(appNum, options);

Try / catch

try {
  await seedFollowup(appNum);
} catch (err) {
  if (err.code === 'ROW_NOT_FOUND' && err.message.includes('Tracker not found')) {
    console.error('Tracker missing — run: node doctor.mjs');
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Fresh repo where onboarding never created data/applications.md; CAREER_OPS_TRACKER env var points to a wrong or deleted path; a custom options.trackerPath argument refers to a non-existent file; running from the wrong working directory so the default relative path misses.

Common situations: First run before doctor.mjs onboarding completes; CI cloned the repo without the data/ directory; env var carried over from a different machine or project root.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/c3af025b065811ff. Report an issue: GitHub.