{"record":{"id":"e7ad4a1ed84ab0df","repo":"jackwener/OpenCLI","slug":"argument-argdef-name-must-be-a-valid-number","errorCode":null,"errorMessage":"Argument \"${argDef.name}\" must be a valid number. Received: \"${val}\"","messagePattern":"Argument \"(.+?)\" must be a valid number\\. Received: \"(.+?)\"","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"src/execution.ts","lineNumber":71,"sourceCode":"\nexport function coerceAndValidateArgs(cmdArgs: Arg[], kwargs: CommandArgs): CommandArgs {\n  const result: CommandArgs = { ...kwargs };\n\n  for (const argDef of cmdArgs) {\n    const val = result[argDef.name];\n\n    if (argDef.required && (val === undefined || val === null || val === '')) {\n      throw new ArgumentError(\n        `Argument \"${argDef.name}\" is required.`,\n        argDef.help ?? `Provide a value for --${argDef.name}`,\n      );\n    }\n\n    if (val !== undefined && val !== null) {\n      if (argDef.type === 'int' || argDef.type === 'number') {\n        const num = Number(val);\n        if (!Number.isFinite(num)) {\n          throw new ArgumentError(`Argument \"${argDef.name}\" must be a valid number. Received: \"${val}\"`);\n        }\n        if (argDef.type === 'int' && !Number.isInteger(num)) {\n          throw new ArgumentError(`Argument \"${argDef.name}\" must be a valid integer. Received: \"${val}\"`);\n        }\n        result[argDef.name] = num;\n      } else if (argDef.type === 'boolean' || argDef.type === 'bool') {\n        if (typeof val === 'string') {\n          const lower = val.toLowerCase();\n          if (lower === 'true' || lower === '1') result[argDef.name] = true;\n          else if (lower === 'false' || lower === '0') result[argDef.name] = false;\n          else throw new ArgumentError(`Argument \"${argDef.name}\" must be a boolean (true/false). Received: \"${val}\"`);\n        } else {\n          result[argDef.name] = Boolean(val);\n        }\n      }\n\n      const coercedVal = result[argDef.name];\n      if (argDef.choices && argDef.choices.length > 0) {","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/execution.ts#L53-L89","documentation":"When an argument definition declares type 'int' or 'number', coerceAndValidateArgs converts the supplied value with Number(). If the result is not finite (NaN/Infinity), it throws ArgumentError stating the value must be a valid number. Note 'int' additionally requires an integer (separate error).","triggerScenarios":"Passing --retries abc, --timeout \"10s\", --count 1_000, or kwargs like { retries: 'fast' } to an argument typed number/int.","commonSituations":"Including units in the value (10s, 5ms); thousands separators or underscores; locale-formatted numbers (1,5); copying string config values into numeric flags.","solutions":["Pass a plain numeric value, e.g. --timeout 30.","Strip units/separators from the value before passing it (parse 10s -> 10 in the script).","For int-typed arguments, also ensure the value has no decimal part.","Coerce in code first: Number(value) and check Number.isFinite before calling."],"exampleFix":"// before\nopencli run --timeout 30s\n// after\nopencli run --timeout 30","handlingStrategy":"validation","validationCode":"function toNumber(v: unknown, label: string): number {\n  const n = Number(v);\n  if (!Number.isFinite(n)) throw new Error(`${label} must be a valid number, got: ${String(v)}`);\n  return n;\n}\nkwargs.timeout = toNumber(kwargs.timeout, '--timeout');","typeGuard":"const isFiniteNumber = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isFinite(v);","tryCatchPattern":"try {\n  await opencli.run(cmd, kwargs);\n} catch (e) {\n  if (/must be a valid number/.test(e.message)) {\n    console.error(`${e.message} — strip units like 's'/'ms' and separators.`);\n  } else throw e;\n}","preventionTips":["Pass bare numbers without units, underscores, commas, or locale formatting.","Parse duration strings ('30s') into numbers before passing.","Pre-coerce and check Number.isFinite in wrappers around the CLI."],"tags":["cli","type-coercion","validation"],"backgroundTag":"invalid-number-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}