{"record":{"id":"108314a181a06cbf","repo":"jackwener/OpenCLI","slug":"page-must-be-a-positive-decimal-integer-got-108314","errorCode":null,"errorMessage":"--page must be a positive decimal integer, got: ${String(value)}","messagePattern":"--page must be a positive decimal integer, got: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/utils.js","lineNumber":91,"sourceCode":"            reject(new Error(`Cannot resolve BV ID from short URL: ${trimmed}`));\n        });\n        req.on('error', reject);\n        req.setTimeout(4000, () => { req.destroy(); reject(new Error(`Timeout resolving short URL: ${trimmed}`)); });\n    });\n}\n/**\n * 解析 --page 选集序号（分P / 视频选集）。\n * 缺省/空串 → null（不下钻，保持整集默认 P1 旧行为）。\n * 非正十进制整数 → 抛 ArgumentError（参数错误，不静默吞）。\n */\nexport function parsePageArg(value) {\n    if (value == null || value === '') return null;\n    if (typeof value === 'number') {\n        if (Number.isSafeInteger(value) && value >= 1) return value;\n        throw new ArgumentError(`--page must be a positive decimal integer, got: ${value}`);\n    }\n    if (typeof value !== 'string' || !/^[1-9]\\d*$/.test(value)) {\n        throw new ArgumentError(`--page must be a positive decimal integer, got: ${String(value)}`);\n    }\n    const n = Number(value);\n    if (!Number.isSafeInteger(n)) {\n        throw new ArgumentError(`--page is too large: ${value}`);\n    }\n    return n;\n}\n\nfunction readApiPositiveInteger(value, label) {\n    if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 1) {\n        return value;\n    }\n    if (typeof value === 'string' && /^[1-9]\\d*$/.test(value)) {\n        const n = Number(value);\n        if (Number.isSafeInteger(n)) return n;\n    }\n    throw new CommandExecutionError(`Bilibili view API returned a malformed ${label}`);\n}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/utils.js#L73-L109","documentation":"The string branch of parsePageArg: any string that is not null/empty and does not fully match /^[1-9]\\d*$/ (a positive decimal integer without leading zeros, signs, or whitespace) throws this ArgumentError with the stringified value. This rejects '0', '-1', '1.5', '01', '1e3', ' 2', and non-strings like objects.","triggerScenarios":"Calling parsePageArg('0'), parsePageArg('-2'), parsePageArg('1.5'), parsePageArg('01'), parsePageArg('abc'), parsePageArg(' 3'), or passing a non-string non-number (object, boolean, array).","commonSituations":"CLI/framework delivering --page with an '=' sign or stray whitespace; zero-padding page numbers; scripts building the flag with a float format; users typing 'page 2' or '2nd'.","solutions":["Pass the page as a plain decimal string like '2' (no sign, no leading zeros, no decimals)","Trim and normalize the value before calling: String(value).trim()","Convert with parseInt(value, 10) and validate Number.isSafeInteger before passing","Fix the CLI argument format (use --page 2, not --page=2.0 or -page 2)"],"exampleFix":"// before\nparsePageArg('01');\n// after\nparsePageArg('1');","handlingStrategy":"validation","validationCode":"function normalizePageStr(v) {\n  const s = String(v ?? '').trim();\n  return /^[1-9]\\d*$/.test(s) ? s : null;\n}\nconst page = normalizePageStr(cliPage);","typeGuard":"function isDecimalPageString(v) {\n  return typeof v === 'string' && /^[1-9]\\d*$/.test(v);\n}","tryCatchPattern":"try {\n  const page = parsePageArg(value);\n} catch (err) {\n  if (err instanceof ArgumentError && /--page/.test(err.message)) {\n    console.error(`--page must look like '2' (got '${value}'); using default`);\n    const page = null;\n  } else throw err;\n}","preventionTips":["Trim and normalize CLI values before validation (whitespace/signs break the regex)","Avoid zero-padded numbers ('01') — pass '1'","Use --page 2 syntax without units or suffixes","Convert to a number early and pass numbers when you control the caller"],"tags":["argument-validation","cli-input","bilibili"],"backgroundTag":"invalid-page-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}