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

  1. 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.
  2. 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.
  3. 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

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)