{"record":{"id":"e05fee7389cf8c8a","repo":"jackwener/OpenCLI","slug":"label-must-be-a-positive-integer-e05fee","errorCode":null,"errorMessage":"${label} must be a positive integer","messagePattern":"(.+?) must be a positive integer","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/qoder/_utils.js","lineNumber":48,"sourceCode":"    }\n    return payload;\n}\n\nexport async function evaluateQoder(page, script) {\n    return unwrapEvaluateResult(await page.evaluate(script));\n}\n\nexport function requireArrayResult(value, label) {\n    if (!Array.isArray(value)) {\n        throw new CommandExecutionError(`${label}: unexpected evaluate result shape`);\n    }\n    return value;\n}\n\nexport function parsePositiveInt(raw, fallback, label) {\n    const value = raw == null || raw === '' ? fallback : Number(raw);\n    if (!Number.isInteger(value) || value < 1) {\n        throw new ArgumentError(`${label} must be a positive integer`);\n    }\n    return value;\n}\n\n// Build a JS snippet that clicks the first visible element matching any\n// of the given CSS selectors. Uses the full pointer-event chain to\n// satisfy radix/headless menu libraries.\nexport function clickFirstScript(selectors) {\n    return `(() => {\n    ${IS_VISIBLE_JS}\n    const sels = ${JSON.stringify(selectors)};\n    for (const sel of sels) {\n      const target = Array.from(document.querySelectorAll(sel)).filter(isVisible)[0];\n      if (target) {\n        const r = target.getBoundingClientRect();\n        const opts = { bubbles: true, cancelable: true, clientX: r.x + r.width/2, clientY: r.y + r.height/2 };\n        target.dispatchEvent(new PointerEvent('pointerdown', opts));\n        target.dispatchEvent(new MouseEvent('mousedown', opts));","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/qoder/_utils.js#L30-L66","documentation":"ArgumentError thrown by parsePositiveInt when a numeric option (limit, timeoutSec) is not a positive integer. Non-numeric strings become NaN and fail the Number.isInteger check; zero, negatives, and floats are also rejected. Empty/null falls back to the provided default rather than throwing.","triggerScenarios":"Calling a qoder command with `--limit 0`, `--limit -5`, `--limit abc`, `--limit 2.5`, or `--timeoutSec 0`; passing a value with units ('30s') or whitespace-padded strings that Number() can't cleanly coerce.","commonSituations":"Shell variables containing invalid values; documentation examples copy-pasted with unit suffixes; users assuming 0 means 'unlimited'; locale-formatted numbers with commas.","solutions":["Pass a plain positive integer, e.g. `--limit 10 --timeoutSec 30`","Omit the option entirely to use the built-in default","Validate numeric flags in wrapper scripts before invoking the CLI"],"exampleFix":"// before\nspawn('qoder', ['items', '--limit', '0']);   // throws\n// after\nspawn('qoder', ['items', '--limit', '10']);","handlingStrategy":"validation","validationCode":"function assertPositiveInt(v) {\n  const n = Number(v);\n  if (!Number.isInteger(n) || n < 1) throw new Error(`${v} is not a positive integer`);\n  return n;\n}\nassertPositiveInt(opts.limit);","typeGuard":"function isPositiveInt(v) { return Number.isInteger(v) && v >= 1; }","tryCatchPattern":"try {\n  await qoderItems({ limit: rawLimit });\n} catch (e) {\n  if (/must be a positive integer/.test(e.message)) {\n    console.error('Pass an integer >= 1 for --limit/--timeoutSec, or omit for the default');\n  } else throw e;\n}","preventionTips":["Validate numeric flags at the script boundary before spawning the CLI","Never pass 0 or unit-suffixed values ('30s') expecting them to be coerced","Rely on built-in defaults by omitting optional numeric flags"],"tags":["qoder","validation","argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}