{"record":{"id":"b33aef9564e62f68","repo":"can1357/oh-my-pi","slug":"multipleof-must-be-greater-than-zero","errorCode":null,"errorMessage":"multipleOf must be greater than zero","messagePattern":"multipleOf must be greater than zero","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/typebox.ts","lineNumber":262,"sourceCode":"\t\tcase \"uuid\":\n\t\t\treturn value => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);\n\t\tcase \"date-time\":\n\t\t\treturn value =>\n\t\t\t\t/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(?:\\.\\d+)?(?:Z|[+-]\\d\\d:\\d\\d)$/.test(value) &&\n\t\t\t\t!Number.isNaN(Date.parse(value));\n\t\tcase \"date\":\n\t\t\treturn value => /^\\d{4}-\\d\\d-\\d\\d$/.test(value) && !Number.isNaN(Date.parse(`${value}T00:00:00Z`));\n\t\tdefault:\n\t\t\treturn () => true;\n\t}\n}\n\nfunction tNumber(opts?: NumberOpts, integer = false): TNumber {\n\tfor (const key of [\"minimum\", \"maximum\", \"exclusiveMinimum\", \"exclusiveMaximum\", \"multipleOf\"] as const) {\n\t\tcheckFiniteOption(key, opts?.[key]);\n\t}\n\tif (opts?.multipleOf !== undefined && opts.multipleOf <= 0)\n\t\tthrow new OmpTypeError(\"multipleOf must be greater than zero\");\n\tlet lower: { value: number; exclusive: boolean } | undefined;\n\tif (opts?.minimum !== undefined) lower = { value: opts.minimum, exclusive: false };\n\tif (opts?.exclusiveMinimum !== undefined && (!lower || opts.exclusiveMinimum >= lower.value)) {\n\t\tlower = { value: opts.exclusiveMinimum, exclusive: true };\n\t}\n\tlet upper: { value: number; exclusive: boolean } | undefined;\n\tif (opts?.maximum !== undefined) upper = { value: opts.maximum, exclusive: false };\n\tif (opts?.exclusiveMaximum !== undefined && (!upper || opts.exclusiveMaximum <= upper.value)) {\n\t\tupper = { value: opts.exclusiveMaximum, exclusive: true };\n\t}\n\tconst keyword = integer ? \"number.integer\" : \"number\";\n\t// The `LO <= TYPE <= HI` range spelling requires both bounds; a min-only\n\t// bound must use the postfix `TYPE >= LO` form (see parseBounded in ir.ts).\n\tlet src: string;\n\tif (lower && upper) {\n\t\tsrc = `${lower.value} ${lower.exclusive ? \"<\" : \"<=\"} ${keyword} ${upper.exclusive ? \"<\" : \"<=\"} ${upper.value}`;\n\t} else if (lower) {\n\t\tsrc = `${keyword} ${lower.exclusive ? \">\" : \">=\"} ${lower.value}`;","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/typebox.ts#L244-L280","documentation":"Beyond finiteness, `tNumber` requires `multipleOf` to be strictly greater than zero. A zero or negative multipleOf is mathematically meaningless for the constraint (every value is a multiple of... nothing) and is rejected at schema construction with this message.","triggerScenarios":"`tNumber({ multipleOf: 0 })`, `tNumber({ multipleOf: -2 })`, or `multipleOf` computed from a variable that ends up 0/negative (e.g. step derived from config defaulting to 0).","commonSituations":"Building dynamic numeric schemas where the step comes from user config or a UI input that can be 0; sign errors when deriving step from a direction-aware value.","solutions":["Ensure the value passed is > 0; validate with `step > 0` before constructing the schema.","If no step constraint is desired, omit `multipleOf` instead of passing 0.","Use `Math.abs()` only if a negative step is acceptable as a magnitude — then pass the absolute value."],"exampleFix":"// before\ntNumber({ multipleOf: options.step }); // step may be 0\n// after\nconst step = options.step > 0 ? options.step : undefined;\ntNumber(step !== undefined ? { multipleOf: step } : undefined);","handlingStrategy":"validation","validationCode":"function positiveMultipleOf(n: number | undefined): number | undefined {\n  if (n === undefined) return undefined;\n  if (!(typeof n === 'number' && Number.isFinite(n) && n > 0)) throw new RangeError(`multipleOf must be > 0, got ${n}`);\n  return n;\n}","typeGuard":"function isValidMultipleOf(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isFinite(v) && v > 0;\n}","tryCatchPattern":"try {\n  const schema = tNumber({ multipleOf: step });\n} catch (err) {\n  if (err instanceof Error && err.message === 'multipleOf must be greater than zero') {\n    throw new Error(`Configured step must be a positive number, got ${step}`);\n  }\n  throw err;\n}","preventionTips":["Validate step/multipleOf inputs at the config boundary (`step > 0`).","Omit multipleOf entirely when no step constraint is intended.","Watch derived values that can hit 0 (empty defaults, division results)."],"tags":["omptype","schema-construction","numeric-options","invalid-argument"],"backgroundTag":"invalid-multiple-of-constraint","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}