can1357/oh-my-pi · error · OmpTypeError
number max must not be NaN
Error message
number max must not be NaN
What it means
omptype's Zod-like `.max()` on a number schema rejects NaN bounds. A NaN bound would make every comparison meaningless and silently invalidate all values, so the library throws an OmpTypeError at schema-construction time instead of failing at validation time. This is a fail-fast guard in `max()` at packages/omptype/src/zod.ts:153.
Source
Thrown at packages/omptype/src/zod.ts:153
const min = ir.min === undefined ? bound : Math.max(ir.min, bound);
return next(restrictBase(schema, { ...ir, min }));
}
if (ir.k === "number") {
if (Number.isNaN(bound)) throw new OmpTypeError("number min must not be NaN");
if (ir.min !== undefined && ir.min >= bound) return next(restrictBase(schema, ir));
return next(restrictBase(schema, { ...ir, min: bound, xmin: false }));
}
throw new OmpTypeError(`cannot apply min to ${ir.k}`);
},
max(bound: number): ZodLikeSchema<Out> {
const ir = schema.ir;
if (ir.k === "string" || ir.k === "array") {
lengthBound("max", schema, bound);
const max = ir.max === undefined ? bound : Math.min(ir.max, bound);
return next(restrictBase(schema, { ...ir, max }));
}
if (ir.k === "number") {
if (Number.isNaN(bound)) throw new OmpTypeError("number max must not be NaN");
if (ir.max !== undefined && ir.max <= bound) return next(restrictBase(schema, ir));
return next(restrictBase(schema, { ...ir, max: bound, xmax: false }));
}
throw new OmpTypeError(`cannot apply max to ${ir.k}`);
},
int(): ZodLikeSchema<Out> {
if (schema.ir.k !== "number") throw new OmpTypeError(`cannot apply int to ${schema.ir.k}`);
return next(restrictBase(schema, { ...schema.ir, int: true }));
},
positive(): ZodLikeSchema<Out> {
if (schema.ir.k !== "number") throw new OmpTypeError(`cannot apply positive to ${schema.ir.k}`);
const ir = schema.ir;
if (ir.min !== undefined && ir.min > 0) return next(restrictBase(schema, ir));
return next(restrictBase(schema, { ...ir, min: 0, xmin: true }));
},
nonnegative(): ZodLikeSchema<Out> {
if (schema.ir.k !== "number") throw new OmpTypeError(`cannot apply nonnegative to ${schema.ir.k}`);
return this.min(0);View on GitHub (pinned to 9690622007)
Solutions
- Check the bound with Number.isNaN() before calling .max() and use a sane fallback
- Trace where the bound value is computed; fix the parse/lookup that produced NaN
- If 'no limit' is intended, skip calling .max() entirely instead of passing NaN
Example fix
// before const limit = Number(process.env.MAX_ITEMS); schema.max(limit); // throws when MAX_ITEMS is undefined // after const parsed = Number(process.env.MAX_ITEMS); const limit = Number.isNaN(parsed) ? 100 : parsed; schema.max(limit);
Defensive patterns
Strategy: validation
Validate before calling
function assertFiniteBound(bound: number, name = "max"): void {
if (!Number.isFinite(bound)) throw new Error(`${name} bound must be finite, got ${bound}`);
}
assertFiniteBound(limit); // before schema.max(limit) Type guard
function isFiniteNumber(v: unknown): v is number {
return typeof v === "number" && Number.isFinite(v);
} Try / catch
try {
schema = base.max(bound);
} catch (err) {
if (err instanceof OmpTypeError && /NaN/.test(err.message)) {
schema = base; // skip the bound and log the bad input
} else throw err;
} Prevention
- Never pass raw Number(envVar)/parseFloat results straight into .max(); run them through Number.isFinite()
- Give config-derived bounds explicit defaults with a validate step
- Prefer omitting the .max() call over passing a sentinel like NaN or Infinity
When it happens
Trigger: Calling `.max(bound)` on a number schema where `Number.isNaN(bound)` is true — typically `.max(someNumber)` where someNumber came from a failed parse (parseFloat/Number of undefined, empty string, or missing config).
Common situations: Config values read from env or JSON that are undefined or non-numeric, then passed to Number()/parseFloat() yielding NaN; arithmetic on missing fields; data-driven bounds from a file with a blank cell.
Related errors
- Invalid number: ${rawValue}
- Invalid Date
- date bound must be valid
- numeric range intersection is unsatisfiable
- numeric bound must be finite
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/27e7cf9dae6acff2.
Report an issue: GitHub.