{"record":{"id":"287de8d0db5ae9fe","repo":"santifer/career-ops","slug":"version-must-be-a-positive-integer","errorCode":null,"errorMessage":"version must be a positive integer","messagePattern":"version must be a positive integer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"application-artifacts.mjs","lineNumber":35,"sourceCode":"const DECISIONS = new Set(['reuse', 'reuse-with-edits', 'regenerate']);\n\n/** Convert a user-facing label into a safe, readable path segment. */\nexport function slugifySegment(value, fallback = 'application') {\n  const slug = String(value ?? '')\n    .trim()\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/^-+|-+$/g, '');\n  return slug || fallback;\n}\n\n/** Return all stable paths belonging to one application artifact bundle. */\nexport function applicationArtifactPaths({ reportNum, company, role, version = 1, root = DEFAULT_OUTPUT_ROOT }) {\n  if (!/^\\d+$/.test(String(reportNum ?? ''))) {\n    throw new Error('reportNum must be a numeric report number');\n  }\n  if (!/^\\d+$/.test(String(version ?? '')) || Number(version) < 1) {\n    throw new Error('version must be a positive integer');\n  }\n  const key = `${String(reportNum).padStart(3, '0')}-${slugifySegment(company)}-${slugifySegment(role, 'role')}`;\n  const applicationRoot = join(resolve(root), key);\n  const tailoredRoot = join(applicationRoot, 'cv', 'tailored', `v${String(version).padStart(3, '0')}`);\n  return {\n    key,\n    root: applicationRoot,\n    jd: {\n      current: join(applicationRoot, 'jd', 'current.md'),\n      previous: join(applicationRoot, 'jd', 'previous.md'),\n    },\n    cv: {\n      source: {\n        html: join(applicationRoot, 'cv', 'source', 'original.html'),\n        pdf: join(applicationRoot, 'cv', 'source', 'original.pdf'),\n      },\n      tailored: {\n        root: tailoredRoot,","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/application-artifacts.mjs#L17-L53","documentation":"Validation in `applicationArtifactPaths`: the optional `version` (default 1) coerced to string must match `/^\\d+$/` AND its numeric value must be ≥ 1. Rejects zero, negatives, decimals, and non-numeric strings, because versions index the `cv/tailored/vNNN` subdirectory and an invalid version would create an unusable path.","triggerScenarios":"Passing `version: 0`, `version: -1`, `version: 1.5`, `version: 'v2'`, `version: ''`, `version: 'latest'`, or `version: undefined`-as-string. Each fails either the digit-only regex or the `< 1` numeric check.","commonSituations":"Caller defaults new versions to 0 expecting auto-increment (the function does not auto-increment); passes a 'v2'-style label; reads version from a config that allowed null; arithmetic producing 0/NaN; off-by-one in a versioning loop.","solutions":["Pass a positive integer: omit it (defaults to 1) or supply `version: 2`, `3`, etc.","Compute the next version explicitly upstream: `const next = (maxExisting || 0) + 1;` then pass `version: next`.","Strip non-digits and validate before calling.","Never use zero or negative versions — the directory layout is `v001`, `v002`, … so version 1 is the first.","Add a test for the 0, negative, and non-numeric rejection paths."],"exampleFix":"// before\napplicationArtifactPaths({ reportNum: 42, company: 'acme', role: 'swe', version: 0 }); // throws\n// after\napplicationArtifactPaths({ reportNum: 42, company: 'acme', role: 'swe', version: 1 });","handlingStrategy":"validation","validationCode":"function positiveIntVersion(v) {\n  const n = Number(v ?? 1);\n  if (!Number.isInteger(n) || n < 1) throw new Error(`version must be a positive integer, got: ${v}`);\n  return n;\n}","typeGuard":"function isPositiveIntVersion(v) {\n  const n = Number(v);\n  return Number.isInteger(n) && n >= 1;\n}","tryCatchPattern":null,"preventionTips":["Omit version to use the default (1); only pass explicit positive integers.","Compute next version upstream as `(maxExisting || 0) + 1`.","Never pass 0, negatives, decimals, or 'vN' labels.","Test rejection of 0, -1, 1.5, 'v2'."],"tags":["validation","path","application-artifacts","version"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}