{"record":{"id":"6a94ea3aa73b54f7","repo":"can1357/oh-my-pi","slug":"cannot-apply-numeric-bound-to-ir-k","errorCode":null,"errorMessage":"cannot apply numeric bound to ${ir.k}","messagePattern":"cannot apply numeric bound to (.+?)","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":2474,"sourceCode":"\treturn Math.min(a, b);\n}\n\nfunction withLengthBound(ir: IR, side: \"min\" | \"max\", bound: number): IR {\n\tif (ir.k === \"array\" || ir.k === \"string\") {\n\t\treturn side === \"min\" ? { ...ir, min: bound } : { ...ir, max: bound };\n\t}\n\tthrow new OmpTypeError(`cannot apply length bound to ${ir.k}`);\n}\n\nfunction withNumericBound(ir: IR, side: \"min\" | \"max\", bound: number, exclusive = false): IR {\n\tif (!Number.isFinite(bound)) throw new OmpTypeError(\"numeric bound must be finite\");\n\tif (ir.k === \"number\") {\n\t\treturn side === \"min\" ? { ...ir, min: bound, xmin: exclusive } : { ...ir, max: bound, xmax: exclusive };\n\t}\n\tif (ir.k === \"union\") {\n\t\treturn { ...ir, members: ir.members.map(member => withNumericBound(member, side, bound, exclusive)) };\n\t}\n\tthrow new OmpTypeError(`cannot apply numeric bound to ${ir.k}`);\n}\ninterface GenericParameter {\n\treadonly name: string;\n\treadonly constraintDef?: unknown;\n}\n\ninterface GenericMeta {\n\treadonly parameters: readonly GenericParameter[];\n\tinstantiateIR(arguments_: readonly IR[]): IR;\n}\n\nconst GENERIC_META = Symbol(\"omptype.generic\");\n\n/** Callable runtime generic returned by `type(\"<t>\", def)` and `type.generic(...)`. */\nexport type Generic = (...arguments_: readonly unknown[]) => BaseType;\n\ninterface RuntimeGeneric extends Generic {\n\treadonly [GENERIC_META]: GenericMeta;","sourceCodeStart":2456,"sourceCodeEnd":2492,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L2456-L2492","documentation":"withNumericBound() applies min/max bounds only to number IR nodes (or unions, by mapping each member). If the resolved IR kind is anything else — string, boolean, object, array, record, etc. — the library throws OmpTypeError because numeric bounds are meaningless there. This is a compile-time-mistake surfaced at runtime: you called .min()/.max() (or equivalent) on a type that isn't a number.","triggerScenarios":"Calling a numeric bound method (min/max style) on a type built from a non-numeric definition, e.g. type('string').min(...) via a path that goes through withNumericBound, or on a union containing non-numeric members.","commonSituations":"Refactoring a schema from number to string/integer-like and forgetting to drop the bound; applying bounds to a generic/aliased definition whose underlying kind isn't number; piping a user-supplied definition into a numeric-bound helper.","solutions":["Ensure the base definition is numeric, e.g. type('number').min(0) instead of type('string').min(0)","If the type is a union, make every member numeric or bound each numeric member individually","Use the correct constraint API for non-numeric kinds (string length, array length) instead of numeric bounds","Catch OmpTypeError at schema-construction time and surface a clearer message to schema authors"],"exampleFix":"// before\nconst t = type('string').min(3); // throws\n// after\nconst t = type('string').atLeastLength(3);\nconst n = type('number').min(3); // numeric bound on number is fine","handlingStrategy":"validation","validationCode":"function assertNumericBounded(def: string) {\n  if (!/^number\\b|union<.*number.*>/.test(def.trim())) {\n    throw new Error(`numeric bounds require a numeric definition, got: ${def}`);\n  }\n}","typeGuard":"function isNumberIR(ir: { k: string }): ir is { k: 'number'; min?: number; max?: number } {\n  return ir.k === 'number' || ir.k === 'union';\n}","tryCatchPattern":"try {\n  const t = type(def).min(bound);\n} catch (err) {\n  if (err instanceof OmpTypeError && err.message.startsWith('cannot apply numeric bound')) {\n    throw new Error(`Schema ${def} is not numeric; use length/range APIs instead`);\n  }\n  throw err;\n}","preventionTips":["Only call .min/.max on definitions you know resolve to number","Prefer kind-specific APIs (atLeastLength for strings) over numeric bounds","Add a unit test per schema that exercises bound construction"],"tags":["schema","validation","numeric-bounds","omptype"],"backgroundTag":"invalid-schema-constraint","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}