{"record":{"id":"1e6295c3aa3ab075","repo":"pydantic/monty","slug":"name-must-be-a-finite-number","errorCode":null,"errorMessage":"{name} must be a finite number","messagePattern":"(.+?) must be a finite number","errorType":"validation","errorClass":"napi::Error","httpStatus":null,"severity":"error","filePath":"crates/monty-js/src/limits.rs","lineNumber":104,"sourceCode":"            Status::InvalidArg,\n            format!(\"{name} must fit in Rust usize on this platform\"),\n        )\n    })\n}\n\n/// 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":86,"sourceCodeEnd":121,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/src/limits.rs#L86-L121","documentation":"napi-rs `Error` (Status::InvalidArg) thrown by `js_number_to_u64` in monty-js when a numeric option (e.g. a resource-limit field) is not a finite JavaScript number (NaN, Infinity, -Infinity). The helper validates f64 inputs coming over the napi boundary before they are narrowed to u64. This is the first guard in an ordered chain of checks.","triggerScenarios":"Calling any monty-js API that sets a numeric limit with `NaN`, `Infinity`, or `-Infinity`, e.g. `Monty.create({ maxMemory: Infinity })` or `pool.checkout({ requestTimeout: NaN })`, when that value flows into `js_number_to_usize` -> `js_number_to_u64`.","commonSituations":"Computing a limit from an arithmetic expression that overflows or divides by zero; loading limits from config where a JSON parser or env-var coercion produced NaN/Infinity; spreading `Infinity` as an 'unlimited' sentinel.","solutions":["Replace NaN/Infinity with a finite number before passing the option","Check `Number.isFinite(value)` on every numeric option before creating a pool/session","If 'unlimited' is intended, omit the field and use the library default instead of Infinity","Sanitize values parsed from JSON/env — `JSON.parse` cannot carry Infinity, so coercion code likely introduced it"],"exampleFix":"// before\nawait Monty.create({ maxMemory: 1024 * 1024 * 1024 * 1024 * 1024 }) // Infinity\n// after\nconst maxMemory = Number.isFinite(opts.maxMemory) ? opts.maxMemory : 100 * 1024 * 1024;\nawait Monty.create({ maxMemory })","handlingStrategy":"validation","validationCode":"function assertFiniteU64Option(name, v) {\n  if (!Number.isFinite(v)) throw new TypeError(`${name} must be a finite number`);\n  return v;\n}","typeGuard":"const isFiniteNumber = (v) => typeof v === 'number' && Number.isFinite(v);","tryCatchPattern":"try {\n  await Monty.create({ maxMemory: rawMaxMemory });\n} catch (e) {\n  if (e instanceof napi.Status && /must be a finite number/.test(e.message)) {\n    // fall back to library default\n  } else throw e;\n}","preventionTips":["Validate all numeric options with Number.isFinite before calls","Never use Infinity as an 'unlimited' sentinel — omit the field instead","Sanitize values coerced from env vars or JSON config"],"tags":["javascript","napi","argument-validation","numbers"],"backgroundTag":"invalid-argument-value","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}