santifer/career-ops · error · Error
reportNum must be a numeric report number
Error message
reportNum must be a numeric report number
What it means
Validation in `applicationArtifactPaths`: the `reportNum` argument, coerced to string, must match `/^\d+$/` (one or more digits only — no padding, sign, decimal, or suffix). Used to build the deterministic artifact directory key, so any non-numeric input would corrupt the on-disk layout and break lookups.
Source
Thrown at application-artifacts.mjs:32
import { fileURLToPath } from 'url';
const DEFAULT_OUTPUT_ROOT = resolve('output');
const DECISIONS = new Set(['reuse', 'reuse-with-edits', 'regenerate']);
/** Convert a user-facing label into a safe, readable path segment. */
export function slugifySegment(value, fallback = 'application') {
const slug = String(value ?? '')
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
return slug || fallback;
}
/** Return all stable paths belonging to one application artifact bundle. */
export function applicationArtifactPaths({ reportNum, company, role, version = 1, root = DEFAULT_OUTPUT_ROOT }) {
if (!/^\d+$/.test(String(reportNum ?? ''))) {
throw new Error('reportNum must be a numeric report number');
}
if (!/^\d+$/.test(String(version ?? '')) || Number(version) < 1) {
throw new Error('version must be a positive integer');
}
const key = `${String(reportNum).padStart(3, '0')}-${slugifySegment(company)}-${slugifySegment(role, 'role')}`;
const applicationRoot = join(resolve(root), key);
const tailoredRoot = join(applicationRoot, 'cv', 'tailored', `v${String(version).padStart(3, '0')}`);
return {
key,
root: applicationRoot,
jd: {
current: join(applicationRoot, 'jd', 'current.md'),
previous: join(applicationRoot, 'jd', 'previous.md'),
},
cv: {
source: {
html: join(applicationRoot, 'cv', 'source', 'original.html'),
pdf: join(applicationRoot, 'cv', 'source', 'original.pdf'),View on GitHub (pinned to 9b17a8ac97)
Solutions
- Pass the bare integer report number as a number or numeric string: `42` or `'42'`.
- Strip non-digits before calling: `reportNum.replace(/\D/g, '')` (then validate it's non-empty).
- If you have a report filename, extract the leading digits first: `(fn.match(/^\D*(\d+)/) || [])[1]`.
- Guard upstream: `if (!/^\d+$/.test(String(reportNum))) throw ...`.
- Pad for display elsewhere (`padStart(3, '0')`) — the function pads internally; do not pre-pad with non-digit chars.
Example fix
// before
applicationArtifactPaths({ reportNum: '042-acme.md', company: 'acme', role: 'swe' }); // throws
// after
applicationArtifactPaths({ reportNum: 42, company: 'acme', role: 'swe' }); Defensive patterns
Strategy: validation
Validate before calling
function numericReportNum(n) {
const s = String(n ?? '');
if (!/^\d+$/.test(s)) throw new Error(`reportNum must be digits only, got: ${n}`);
return s;
} Type guard
function isNumericReportNum(n) {
return /^\d+$/.test(String(n ?? ''));
} Prevention
- Pass the bare integer (42 or '42'); don't include dashes/suffixes.
- Extract the leading number from a filename before passing: `(fn.match(/(\d+)/) || [])[1]`.
- Strip non-digits if accepting user input: `String(n).replace(/\D/g, '')`.
- Guard in the caller with the same regex used internally.
When it happens
Trigger: Passing `reportNum: '042-report'`, `'42.0'`, `'-1'`, `'#42'`, `undefined`/`null` (coerces to 'undefined'), `NaN`, or a report filename slug instead of the bare number.
Common situations: Caller passes the report filename (`'042-acme-2024-01-01.md'`) instead of the number; passes a padded-with-dash slug; reads the value from a regex capture that included extra chars; off-by-one in a loop producing `undefined`; using `Number.parseInt` then stringifying `NaN`.
Related errors
- version must be a positive integer
- decision must be one of: ${[...DECISIONS].join(', ')}
- payload must include at least one of: cv, articleDigest
- payload.cv requires { section, entry }
- payload.cv requires a non-empty dedupKey (used for dedup/ide
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/91fc7310eb540f98.
Report an issue: GitHub.