{"record":{"id":"bc851587b27700ea","repo":"TheAlgorithms/JavaScript","slug":"input-should-be-a-non-negative-whole-number","errorCode":null,"errorMessage":"Input should be a non-negative whole number","messagePattern":"Input should be a non-negative whole number","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"Recursive/Factorial.js","lineNumber":13,"sourceCode":"/**\n * @function Factorial\n * @description function to find factorial using recursion.\n * @param {Integer} n - The input integer\n * @return {Integer} - Factorial of n.\n * @see [Factorial](https://en.wikipedia.org/wiki/Factorial)\n * @example 5! = 1*2*3*4*5 = 120\n * @example 2! = 1*2 = 2\n */\n\nconst factorial = (n) => {\n  if (!Number.isInteger(n) || n < 0) {\n    throw new RangeError('Input should be a non-negative whole number')\n  }\n\n  if (n === 0) {\n    return 1\n  }\n\n  return n * factorial(n - 1)\n}\n\nexport { factorial }\n","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/TheAlgorithms/JavaScript/blob/5c39e87a9a31f279c60f830ad74a845e4788a517/Recursive/Factorial.js#L1-L24","documentation":"Thrown by `factorial(n)` (recursive) when `!Number.isInteger(n) || n < 0`. This is a `RangeError` (not TypeError), and it correctly catches NaN, floats, negatives, and non-numbers in one check because `Number.isInteger` is false for all of those. This is the most thorough input guard in the set.","triggerScenarios":"Call `factorial(-1)`, `factorial(3.5)`, `factorial(NaN)`, `factorial('5')`, `factorial(undefined)`, `factorial(Infinity)`. All non-negative integers (including 0, which returns 1) pass.","commonSituations":"Floating-point math producing a non-integer by accident, negative numbers from sign errors, or unguarded user input.","solutions":["Validate `Number.isInteger(n) && n >= 0` upstream (matches the function's own guard).","Coerce integer-like strings with `Number(n)` and check `Number.isInteger`.","For large n, prefer an iterative factorial to avoid stack overflow - the recursive version has no guard against deep recursion."],"exampleFix":"// before\nfactorial(userInput) // userInput could be -1 or 3.5\n\n// after\nconst n = Number(userInput)\nif (!Number.isInteger(n) || n < 0) throw new RangeError('n must be a non-negative integer')\nfactorial(n)","handlingStrategy":"validation","validationCode":"const n = Number(input)\nif (!Number.isInteger(n) || n < 0) {\n  throw new RangeError('n must be a non-negative integer')\n}\nfactorial(n)","typeGuard":"const isNonNegativeInt = (x) => typeof x === 'number' && Number.isInteger(x) && x >= 0","tryCatchPattern":null,"preventionTips":["The library's own guard (Number.isInteger + n >= 0) is the model - mirror it upstream.","For large n, switch to an iterative factorial to avoid stack overflow.","Coerce string input with Number() and re-check integrality."],"tags":["range-validation","recursion","math","integer-only"],"backgroundTag":null,"analyzedSha":"5c39e87a9a31f279c60f830ad74a845e4788a517","analyzedAt":"2026-08-13T04:54:54.474Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}