{"record":{"id":"2b8f524cf0c425e2","repo":"santifer/career-ops","slug":"not-applied","errorCode":"NOT_APPLIED","errorMessage":"Application #${appNum} is not Applied (status: \"${row.status.trim()}\"); use --force to seed anyway","messagePattern":"Application #(.+?) is not Applied \\(status: \"(.+?)\"\\); use --force to seed anyway","errorType":"validation","errorClass":"SeedError","httpStatus":null,"severity":"warning","filePath":"followup-seed.mjs","lineNumber":435,"sourceCode":"  if (options.date != null && !isValidCalendarDate(options.date)) {\n    throw new SeedError('INVALID_DATE', `--date must be a real calendar date in YYYY-MM-DD form: ${options.date}`);\n  }\n\n  const trackerPath = resolveTrackerPath(options.trackerPath);\n  const followupsPath = resolveFollowupsPath(options.followupsPath);\n\n  if (!existsSync(trackerPath)) {\n    throw new SeedError('ROW_NOT_FOUND', `Tracker not found at ${trackerPath}`);\n  }\n  const rows = readTrackerRows(trackerPath);\n  const row = rows.find(r => r.num === appNum);\n  if (!row) {\n    throw new SeedError('ROW_NOT_FOUND', `Application #${appNum} not found in ${trackerPath}`);\n  }\n\n  const normalized = normalizeStatus(row.status);\n  if (normalized !== 'applied' && !options.force) {\n    throw new SeedError('NOT_APPLIED', `Application #${appNum} is not Applied (status: \"${row.status.trim()}\"); use --force to seed anyway`);\n  }\n\n  const appliedDate = resolveAppliedDate(row, options.date);\n  const cadence = resolveCadenceConfig({ profilePath: options.profilePath });\n  const nextDate = addDays(parseDate(appliedDate), cadence.applied_first);\n  const setDate = todayStr();\n  const pin = formatPinLine(appNum, nextDate, setDate);\n\n  if (options.dryRun) {\n    const existingContent = existsSync(followupsPath) ? readFileSync(followupsPath, 'utf-8') : '';\n    if (isAlreadySeeded(existingContent, appNum) && !options.force) {\n      return { seeded: false, appNum, pin: null, nextDate, appliedDate, setDate, reason: 'already-seeded', dryRun: true };\n    }\n    return { seeded: true, appNum, pin, nextDate, appliedDate, setDate, dryRun: true };\n  }\n\n  const lockDir = resolveLockDir(options.lockDir, followupsPath);\n  const lock = await acquireFollowupsLock(lockDir, followupsPath, {","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/followup-seed.mjs#L417-L453","documentation":"The row was found but its status does not normalize to 'applied'. Follow-up seeding only makes sense for Applied rows because the cadence clock starts at application submission (applied_first offset from resolveAppliedDate). Thrown only when options.force is falsy. normalizeStatus handles lowercase, trailing dates, localized variants, and markdown bold.","triggerScenarios":"Row status is 'Evaluated', 'Responded', 'Interview', 'Rejected', 'Discarded', or 'Offer'; trying to seed before marking the row Applied; the row was Applied but was since advanced to Responded.","commonSituations":"User tries to seed a follow-up before running set-status.mjs to mark Applied; wanting to retroactively seed a row that is now in Interview; seeding after the row was rejected.","solutions":["Mark the row Applied first: node set-status.mjs <appNum> Applied, then seed.","If you genuinely want to seed regardless of status, pass --force (or options.force: true)."],"exampleFix":"// before\nawait seedFollowup(42);\n// throws: Application #42 is not Applied (status: \"Evaluated\")\n\n// after — option 1: mark Applied first\n// node set-status.mjs 42 Applied\nawait seedFollowup(42);\n\n// after — option 2: force seed\nawait seedFollowup(42, { force: true });","handlingStrategy":"validation","validationCode":"import { normalizeStatus } from './followup-cadence.mjs';\n\nconst normalized = normalizeStatus(row.status);\nif (normalized !== 'applied') {\n  // Option A: mark Applied first via set-status.mjs\n  // Option B: pass force: true if you understand the implication\n  throw new Error(`Row is ${row.status}, not Applied. Mark Applied or use --force.`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await seedFollowup(appNum);\n} catch (err) {\n  if (err.code === 'NOT_APPLIED') {\n    console.error(err.message);\n    // Decide: mark Applied, or force seed\n    // await seedFollowup(appNum, { force: true });\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Always mark a row Applied via set-status.mjs before seeding its follow-up.","Use --force only when you understand the cadence will start from a possibly wrong date.","Integrate seeding into the Applied-status transition workflow so it never fires on non-Applied rows."],"tags":["validation","workflow","status","followups"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}