santifer/career-ops · error · SeedError
USAGE
USAGE
Error message
Invalid appNum: ${appNum} What it means
seedFollowup requires the application tracker number to be a positive integer. Before doing any I/O it validates appNum and throws a SeedError with code USAGE if it is not an integer greater than 0. This is a caller-contract error: the wrong type or value was passed for the tracker row id.
Solutions
- Pass the tracker row number as a positive integer: seedFollowup(42).
- Convert string input explicitly: seedFollowup(Number.parseInt(raw, 10)).
- Guard against 0/negative/NaN values before calling.
- Check the tracker table to confirm the actual row # before seeding.
Example fix
// before
await seedFollowup(process.argv[2]);
// after
const appNum = Number.parseInt(process.argv[2], 10);
if (!Number.isInteger(appNum) || appNum <= 0) {
console.error('Usage: seed <appNum> where appNum is a positive integer');
process.exit(1);
}
await seedFollowup(appNum); Defensive patterns
Strategy: validation
Validate before calling
function isValidAppNum(n) {
return Number.isInteger(n) && n > 0;
}
if (!isValidAppNum(appNum)) throw new Error(`appNum must be a positive integer, got ${appNum}`); Type guard
const isAppNum = (v) => typeof v === 'number' && Number.isInteger(v) && v > 0;
Try / catch
try {
await seedFollowup(appNum);
} catch (e) {
if (e.code === 'USAGE') {
console.error(`Bad appNum: ${e.message}. Pass the integer tracker row #.`);
process.exitCode = 2;
} else throw e;
} Prevention
- Parse CLI args with Number.parseInt(raw, 10) instead of passing raw strings.
- Validate row numbers at the boundary where they enter your script (TSV/JSON/argv).
- Remember tracker rows are 1-indexed integers — never pass 0 or computed indices.
- Log the value and typeof appNum when automating so type slips surface early.
When it happens
Trigger: Calling seedFollowup('42') (string instead of number), seedFollowup(0), seedFollowup(-3), seedFollowup(NaN), or a float like 4.5; passing a value parsed from CLI args without Number.parseInt conversion.
Common situations: Script glue that passes process.argv entries directly (always strings); off-by-one generation of row numbers starting at 0; JSON payloads where the id arrived as a string from an API or TSV cell.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Application Answers section has
- changedSections must be an array
- decision must be one of
- --from and --to must both be supplied together (or neither…
- --from ( ) must not be after --to ( ).
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/18b58a3d2d6f84d4.
Report an issue: GitHub.
Appendix: source
Thrown at followup-seed.mjs:545
*/
export async function withFollowupsLock(followupsPath, fn, options = {}) {
const resolvedPath = resolveFollowupsPath(followupsPath);
const lockDir = resolveLockDir(options.lockDir, resolvedPath);
const lock = await acquireFollowupsLock(lockDir, resolvedPath, {
timeoutMs: options.timeoutMs ?? envInt('CAREER_OPS_FOLLOWUPS_LOCK_TIMEOUT_MS', 60_000),
retryMs: options.retryMs ?? envInt('CAREER_OPS_FOLLOWUPS_LOCK_RETRY_MS', 75),
staleMs: options.staleMs ?? envInt('CAREER_OPS_FOLLOWUPS_LOCK_STALE_MS', 10 * 60_000),
});
try {
return await fn();
} finally {
lock.release();
}
}
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);View on GitHub (pinned to aac998c7ed)