{"record":{"id":"6069abaa0575f94d","repo":"jackwener/OpenCLI","slug":"label-must-be-a-positive-positive-f","errorCode":null,"errorMessage":"${label} must be a ${positive ? 'positive ' : ''}finite number","messagePattern":"(.+?) must be a (.+?)finite number","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/geogebra/utils.js","lineNumber":45,"sourceCode":"  if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(normalized)) {\n    throw new ArgumentError(`${label} must be an ASCII GeoGebra label like A, B1, or poly_1`);\n  }\n  return normalized;\n}\n\nexport function normalizeLabelList(value, label, min, max = Infinity) {\n  const parts = String(value ?? '').split(',').map(s => s.trim()).filter(Boolean);\n  if (parts.length < min || parts.length > max) {\n    throw new ArgumentError(`${label} must contain ${min === max ? min : `${min}-${max}`} comma-separated labels`);\n  }\n  return parts.map((part, idx) => normalizeLabel(part, `${label}[${idx + 1}]`));\n}\n\nexport function normalizeNumber(value, label, { defaultValue, positive = false } = {}) {\n  const raw = value == null || value === '' ? defaultValue : value;\n  const number = Number(raw);\n  if (!Number.isFinite(number) || (positive && number <= 0)) {\n    throw new ArgumentError(`${label} must be a ${positive ? 'positive ' : ''}finite number`);\n  }\n  return number;\n}\n\nexport function normalizeCoords(value) {\n  const parts = String(value ?? '').split(',').map(s => s.trim());\n  if (parts.length !== 2) {\n    throw new ArgumentError('coords must be in \"x,y\" format (e.g. \"1,2\")');\n  }\n  return parts.map((part, idx) => normalizeNumber(part, idx === 0 ? 'x' : 'y'));\n}\n\nexport function requireGgbSuccess(result, message) {\n  if (!isPlainObject(result)) {\n    throw new CommandExecutionError(`${message}: malformed GeoGebra result`);\n  }\n  if (!result.ok) {\n    throw new CommandExecutionError(result.error || message);","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/geogebra/utils.js#L27-L63","documentation":"normalizeNumber() validates that a caller-supplied value converts to a finite JavaScript number before it is used in GeoGebra commands. It throws ArgumentError whenever the raw value is null/empty without a defaultValue, or Number(value) yields NaN/Infinity, or the `positive` flag is set and the value is <= 0. The label parameter names the offending field so callers can tell which argument failed.","triggerScenarios":"Passing a non-numeric string (e.g. 'abc'), null/undefined with no defaultValue, an empty string, Infinity, or a zero/negative value while positive=true (e.g. normalizeNumber('0', 'size', { positive: true })). All callers (size, normalizeCoords, normalizedMinCount, normalizedTimeoutMs) route through this check.","commonSituations":"CLI flags typed incorrectly (missing digits, commas as decimal separators under some locales), config files with blank fields, script variables that are undefined due to a typo, or passing a numeric string like '1e999' which parses to Infinity.","solutions":["Print/inspect the value passed for the labeled field and ensure it is a plain finite number (e.g. Number.isFinite(Number(value))).","Supply a defaultValue option for optional parameters so empty input does not throw.","If the field must be positive, pass a value > 0 (e.g. clamp with Math.max(0.1, value)).","Fix the source of the bad input: correct the CLI flag, env var, or config entry that feeds this argument."],"exampleFix":"// before\nnormalizeNumber(opts.timeout, 'timeoutMs', { positive: true })\n// after\nconst timeoutMs = normalizeNumber(opts.timeout ?? 5000, 'timeoutMs', { defaultValue: 5000, positive: true });","handlingStrategy":"validation","validationCode":"function isValidNumber(v) { return v !== '' && v != null && Number.isFinite(Number(v)); }\nif (!isValidNumber(size)) throw new Error('size must be a finite number');","typeGuard":"const isFiniteNumber = (v) => typeof v === 'number' && Number.isFinite(v);","tryCatchPattern":"try { const n = normalizeNumber(input, 'size', { positive: true }); } catch (e) { if (e instanceof ArgumentError) { console.error(`Bad input for ${e.message}`); } else throw e; }","preventionTips":["Coerce and check with Number.isFinite before passing any numeric argument.","Always pass a defaultValue for optional numeric parameters.","Clamp positive-only values with Math.max before calling.","Validate CLI/config input at the boundary with a schema (e.g. zod) before it reaches tool calls."],"tags":["argument-validation","input-validation","cli"],"backgroundTag":"invalid-number-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}