{"record":{"id":"28f41809f2cc6506","repo":"colinhacks/zod","slug":"cannot-mix-number-and-bigint-in-multiple-of-check","errorCode":null,"errorMessage":"Cannot mix number and bigint in multiple_of check.","messagePattern":"Cannot mix number and bigint in multiple_of check\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/checks.ts","lineNumber":178,"sourceCode":"  def: $ZodCheckMultipleOfDef<T>;\n  issc: errors.$ZodIssueNotMultipleOf;\n}\n\nexport interface $ZodCheckMultipleOf<T extends number | bigint = number | bigint> extends $ZodCheck<T> {\n  _zod: $ZodCheckMultipleOfInternals<T>;\n}\n\nexport const $ZodCheckMultipleOf: core.$constructor<$ZodCheckMultipleOf<number | bigint>> =\n  /*@__PURE__*/ core.$constructor(\"$ZodCheckMultipleOf\", (inst, def) => {\n    $ZodCheck.init(inst, def);\n\n    inst._zod.onattach.push((inst) => {\n      inst._zod.bag.multipleOf ??= def.value;\n    });\n\n    inst._zod.check = (payload) => {\n      if (typeof payload.value !== typeof def.value)\n        throw new Error(\"Cannot mix number and bigint in multiple_of check.\");\n      const isMultiple =\n        typeof payload.value === \"bigint\"\n          ? payload.value % (def.value as bigint) === BigInt(0)\n          : util.floatSafeRemainder(payload.value, def.value as number) === 0;\n\n      if (isMultiple) return;\n      payload.issues.push({\n        origin: typeof payload.value as \"number\",\n        code: \"not_multiple_of\",\n        divisor: def.value as number,\n        input: payload.value,\n        inst,\n        continue: !def.abort,\n      });\n    };\n  });\n\n/////////////////////////////////////","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/checks.ts#L160-L196","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before (throws at parse — type mismatch)\nconst Schema = z.bigint().multipleOf(5);\nSchema.parse(15n);\n\n// after (types aligned)\nconst Schema = z.bigint().multipleOf(5n);\nSchema.parse(15n);","handlingStrategy":"type-guard","validationCode":"function buildMultipleOfCheck(value) {\n  return typeof value === 'bigint'\n    ? checks.multipleOf(value) // for z.bigint()\n    : checks.multipleOf(value); // for z.number()\n}\n// Ensure the schema's accepted type matches: z.bigint() -> bigint divisor; z.number() -> number divisor.","typeGuard":"function matchingMultipleOf(schema, divisor) {\n  const schemaIsBigint = schema._zod.def.type === 'bigint';\n  return schemaIsBigint ? typeof divisor === 'bigint' : typeof divisor === 'number';\n}","tryCatchPattern":"try {\n  schema.parse(input);\n} catch (e) {\n  if (e.message === 'Cannot mix number and bigint in multiple_of check.') {\n    // The divisor type doesn't match the schema type — realign and retry\n    throw new Error('multipleOf divisor type must match schema (number vs bigint)');\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["multiple-of","bigint","number","parse-time","type-mismatch"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}