colinhacks/zod · error · Error
Cannot mix number and bigint in multiple_of check.
Error message
Cannot mix number and bigint in multiple_of check.
What it means
Thrown at parse time by the multiple_of check when the type of the parsed value (number vs bigint) does not match the type of the divisor stored in the check definition. The check deliberately refuses to compare across number/bigint because the semantics (and the modulo operation used) differ between the two.
Solutions
- Match the divisor type to the schema: use a bigint literal (e.g. 5n) with z.bigint().multipleOf and a plain number with z.number().multipleOf.
- If input may arrive in either form, coerce or branch first (z.union([z.number(), z.bigint()])) so each branch's multipleOf matches its own type.
- When constructing checks generically, branch on typeof value to build the right check: value > Number.MAX_SAFE_INTEGER ? BigInt(value) : Number(value).
Example fix
// before (throws at parse — type mismatch) const Schema = z.bigint().multipleOf(5); Schema.parse(15n); // after (types aligned) const Schema = z.bigint().multipleOf(5n); Schema.parse(15n);
Defensive patterns
Strategy: type-guard
Validate before calling
function buildMultipleOfCheck(value) {
return typeof value === 'bigint'
? checks.multipleOf(value) // for z.bigint()
: checks.multipleOf(value); // for z.number()
}
// Ensure the schema's accepted type matches: z.bigint() -> bigint divisor; z.number() -> number divisor. Type guard
function matchingMultipleOf(schema, divisor) {
const schemaIsBigint = schema._zod.def.type === 'bigint';
return schemaIsBigint ? typeof divisor === 'bigint' : typeof divisor === 'number';
} Try / catch
try {
schema.parse(input);
} catch (e) {
if (e.message === 'Cannot mix number and bigint in multiple_of check.') {
// The divisor type doesn't match the schema type — realign and retry
throw new Error('multipleOf divisor type must match schema (number vs bigint)');
}
throw e;
} Prevention
- Always use bigint literals (5n) with z.bigint().multipleOf and plain numbers with z.number().multipleOf.
- Avoid reusing a single multipleOf check across both number and bigint schemas.
- If input can arrive as either, branch with z.union and give each branch a type-matched divisor.
When it happens
Trigger: Defining z.bigint().multipleOf(5) (number divisor) and parsing a bigint, or z.number().multipleOf(5n) (bigint divisor) and parsing a number. Constructing a $ZodCheckMultipleOf directly with a value whose type differs from the schema's accepted type. Feeding untyped/un coerced input that swaps the numeric category.
Common situations: Mixed numeric pipelines where some values arrive as BigInt (JSON.parse of large integers, BigInt columns) and the schema was declared for plain numbers, or vice versa. Reusing a multipleOf check across both z.number() and z.bigint() contexts.
Related errors
AI-assisted analysis of colinhacks/zod@2d90846af9 (2026-08-11).
Data as JSON: /api/errors/28f41809f2cc6506.
Report an issue: GitHub.
Appendix: source
Thrown at packages/zod/src/v4/core/checks.ts:178
def: $ZodCheckMultipleOfDef<T>;
issc: errors.$ZodIssueNotMultipleOf;
}
export interface $ZodCheckMultipleOf<T extends number | bigint = number | bigint> extends $ZodCheck<T> {
_zod: $ZodCheckMultipleOfInternals<T>;
}
export const $ZodCheckMultipleOf: core.$constructor<$ZodCheckMultipleOf<number | bigint>> =
/*@__PURE__*/ core.$constructor("$ZodCheckMultipleOf", (inst, def) => {
$ZodCheck.init(inst, def);
inst._zod.onattach.push((inst) => {
inst._zod.bag.multipleOf ??= def.value;
});
inst._zod.check = (payload) => {
if (typeof payload.value !== typeof def.value)
throw new Error("Cannot mix number and bigint in multiple_of check.");
const isMultiple =
typeof payload.value === "bigint"
? payload.value % (def.value as bigint) === BigInt(0)
: util.floatSafeRemainder(payload.value, def.value as number) === 0;
if (isMultiple) return;
payload.issues.push({
origin: typeof payload.value as "number",
code: "not_multiple_of",
divisor: def.value as number,
input: payload.value,
inst,
continue: !def.abort,
});
};
});
/////////////////////////////////////View on GitHub (pinned to 2d90846af9)