{"record":{"id":"c203be4ea541ddb6","repo":"pydantic/monty","slug":"name-must-be-a-safe-integer-9007199254740991","errorCode":null,"errorMessage":"{name} must be a safe integer (<= 9007199254740991)","messagePattern":"(.+?) must be a safe integer \\(<= 9007199254740991\\)","errorType":"validation","errorClass":"napi::Error","httpStatus":null,"severity":"error","filePath":"crates/monty-js/src/limits.rs","lineNumber":110,"sourceCode":"/// Converts a JavaScript `number` used for a size/count limit into `u64`.\n///\n/// JavaScript numbers are IEEE-754 doubles, so integers above `2^53 - 1`\n/// cannot be represented exactly. Rejecting values outside the safe integer\n/// range avoids silently rounding resource limits at the napi boundary.\n///\n/// Returns `Err` for non-finite, negative, fractional, or out-of-range inputs.\n/// This helper does not panic.\npub(crate) fn js_number_to_u64(value: f64, name: &str) -> Result<u64> {\n    const JS_MAX_SAFE_INTEGER: u64 = (1_u64 << 53) - 1;\n\n    match value {\n        v if !v.is_finite() => Err(Error::new(\n            Status::InvalidArg,\n            format!(\"{name} must be a finite number\"),\n        )),\n        v if v < 0.0 => Err(Error::new(Status::InvalidArg, format!(\"{name} must be non-negative\"))),\n        v if v.fract() != 0.0 => Err(Error::new(Status::InvalidArg, format!(\"{name} must be an integer\"))),\n        v if v > JS_MAX_SAFE_INTEGER as f64 => Err(Error::new(\n            Status::InvalidArg,\n            format!(\"{name} must be a safe integer (<= {JS_MAX_SAFE_INTEGER})\"),\n        )),\n        v => {\n            #[expect(clippy::cast_possible_truncation, clippy::cast_sign_loss)]\n            let value = v as u64;\n            Ok(value)\n        }\n    }\n}\n","sourceCodeStart":92,"sourceCodeEnd":121,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/src/limits.rs#L92-L121","documentation":"napi-rs `Error` (Status::InvalidArg) thrown by `js_number_to_u64` when a numeric option exceeds `Number.MAX_SAFE_INTEGER` (2^53 - 1 = 9007199254740991). Beyond that, doubles cannot represent every integer exactly, so the helper refuses to cast to `u64`.","triggerScenarios":"Passing a limit greater than 9007199254740991, e.g. a byte-count above ~9 PB (`maxMemory: 10 ** 16`) or any value from BigInt arithmetic that lost precision via `Number(...)`.","commonSituations":"Configuring sizes in bytes at petabyte scale; converting from BigInt with `Number()` instead of using an exact path; accidental exponent typos (`1e16`).","solutions":["Use a value <= Number.MAX_SAFE_INTEGER, or express the limit in smaller units (MiB)","If a larger value is genuinely needed, use BigInt and convert with an explicit range check first","Omit the option to use the library default"],"exampleFix":"// before\nconst maxMemory = BigInt(opts.maxMemoryBytes);\nawait Monty.create({ maxMemory: Number(maxMemory) }) // precision loss / rejection\n// after\nconst maxMemory = Number(opts.maxMemoryBytes); // caller guarantees <= MAX_SAFE_INTEGER\nawait Monty.create({ maxMemory })","handlingStrategy":"validation","validationCode":"const MAX_SAFE = 2 ** 53 - 1;\nfunction assertSafeInteger(name, v) {\n  if (typeof v === 'number' && v > MAX_SAFE) throw new RangeError(`${name} must be <= ${MAX_SAFE}`);\n  return v;\n}","typeGuard":"const isSafeInteger = (v) => Number.isInteger(v) && Math.abs(v) <= Number.MAX_SAFE_INTEGER;","tryCatchPattern":"try {\n  await Monty.create({ maxMemory: rawBytes });\n} catch (e) {\n  if (/safe integer/.test(e?.message ?? '')) {\n    // express the limit in smaller units or clamp to MAX_SAFE_INTEGER\n  } else throw e;\n}","preventionTips":["Express very large limits in MiB/GiB rather than raw bytes","Avoid Number() on BigInt values without a range check","Remember JS doubles lose integer precision above 2^53-1"],"tags":["javascript","napi","argument-validation","numbers","precision"],"backgroundTag":"value-out-of-range","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}