{"record":{"id":"d481446dad4cbaac","repo":"santifer/career-ops","slug":"invalid-page-budget-maxpages-use-a-positive","errorCode":null,"errorMessage":"Invalid page budget \"${maxPages}\". Use a positive integer.","messagePattern":"Invalid page budget \"(.+?)\"\\. Use a positive integer\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"generate-pdf.mjs","lineNumber":1024,"sourceCode":"}\n\n/**\n * Decide whether a rendered CV fits its configured page budget.\n *\n * This is deliberately separate from rendering: page count comes from the\n * PDF Chromium actually produced, and the renderer never changes layout to\n * force content under the limit.\n *\n * @param {number} pageCount - Actual pages in the rendered PDF.\n * @param {{ maxPages?: number, strictPages?: boolean }} [options]\n * @returns {void}\n */\nexport function enforcePageBudget(pageCount, { maxPages = 2, strictPages = false } = {}) {\n  if (!Number.isInteger(pageCount) || pageCount < 1) {\n    throw new Error(`Could not determine the rendered PDF page count (received ${pageCount}).`);\n  }\n  if (!Number.isInteger(maxPages) || maxPages < 1) {\n    throw new Error(`Invalid page budget \"${maxPages}\". Use a positive integer.`);\n  }\n  if (pageCount <= maxPages) return;\n\n  const actualLabel = 'pages';\n  const allowedLabel = maxPages === 1 ? 'page' : 'pages';\n  const message =\n    `CV is ${pageCount} ${actualLabel}; the allowed maximum is ${maxPages} ${allowedLabel}. ` +\n    'Trim lower-priority bullets, older roles, secondary projects, or the competencies strip, then regenerate.';\n\n  if (strictPages) {\n    throw new Error(`${message} (--strict-pages requested)`);\n  }\n\n  console.warn(`⚠️  ${message} Continuing because overflow is warning-only by default; use --strict-pages to reject it.`);\n}\n\n/**\n * Read the page count from the PDF catalog's root /Pages dictionary.","sourceCodeStart":1006,"sourceCodeEnd":1042,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/generate-pdf.mjs#L1006-L1042","documentation":"enforcePageBudget validates the maxPages option as well: it must be a positive integer (default 2). A non-integer, zero, negative, or non-numeric budget is rejected with this message before any comparison happens, so a mistyped configuration cannot silently allow or block everything.","triggerScenarios":"Calling enforcePageBudget with maxPages: 0, -1, '2', NaN, or Infinity — typically from a CLI flag like --max-pages=0 parsed as a number without validation, or a config file carrying maxPages: \"two\".","commonSituations":"Users setting a 1-page CV budget with a malformed flag value (--max-pages=one), YAML config quoting the number as a string that later fails coercion, or an off-by-one attempt to 'disable' the budget using 0.","solutions":["Pass a positive integer, e.g. --max-pages=1 or maxPages: 1","If the value comes from a string flag/config, coerce with parseInt/Number and validate Number.isInteger(n) && n >= 1 before calling","Remember the budget cannot be disabled via 0 — trim the CV or raise the budget instead"],"exampleFix":"// before\nenforcePageBudget(pageCount, { maxPages: Number(opts.maxPages) }); // '2x' -> NaN\n// after\nconst maxPages = parseInt(opts.maxPages, 10);\nif (!Number.isInteger(maxPages) || maxPages < 1) throw new Error(`--max-pages must be a positive integer, got ${opts.maxPages}`);\nenforcePageBudget(pageCount, { maxPages, strictPages: opts.strictPages });","handlingStrategy":"validation","validationCode":"const maxPages = Number.parseInt(flagValue, 10);\nif (!Number.isInteger(maxPages) || maxPages < 1) {\n  throw new Error(`--max-pages must be a positive integer, got \"${flagValue}\"`);\n}\nenforcePageBudget(pageCount, { maxPages, strictPages: strict });","typeGuard":"const isValidBudget = (n) => Number.isInteger(n) && n >= 1;","tryCatchPattern":"try {\n  enforcePageBudget(pageCount, { maxPages });\n} catch (err) {\n  if (err.message.includes('Invalid page budget')) {\n    console.error('Fix --max-pages (or config maxPages):', err.message);\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Parse numeric CLI flags with parseInt/Number and validate before use","Never use 0 or negative values to 'disable' the budget — remove the limit option instead","Quote-check YAML/JSON config so numeric budgets are not strings","Add a CLI-arg unit test covering the default budget (2) and a custom positive integer"],"tags":["validation","cli","config"],"backgroundTag":"invalid-argument-value","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}