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
- Run node doctor.mjs --json to confirm whether onboarding is needed.
- Verify data/applications.md exists; if not, create it with the tracker header (see AGENTS.md Step 4).
- Check CAREER_OPS_TRACKER env var: echo $CAREER_OPS_TRACKER and ensure it resolves to a real file.
- 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
- Run node doctor.mjs --json at session start to confirm the tracker exists.
- Set CAREER_OPS_TRACKER explicitly in CI to avoid working-directory ambiguity.
- Treat a missing tracker as an onboarding failure, not a runtime error.
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
- Cannot read benchmarks at ${path}: ${err.message}
- portals.yml not found
- vdab: entry "${entry.name || '(unnamed)'}" has no vdab.keywo
- Malformed states file at ${statesPath}: expected a top-level
- Malformed states file at ${statesPath}: expected a top-level
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/c3af025b065811ff.
Report an issue: GitHub.