{"record":{"id":"81d9f33517344552","repo":"TheAlgorithms/Python","slug":"number-must-be-a-positive-integer","errorCode":null,"errorMessage":"{number=} must be a positive integer","messagePattern":"(.+?) must be a positive integer","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"maths/special_numbers/happy_number.py","lineNumber":36,"sourceCode":"    Traceback (most recent call last):\r\n        ...\r\n    ValueError: number=0 must be a positive integer\r\n    >>> is_happy_number(-19)\r\n    Traceback (most recent call last):\r\n        ...\r\n    ValueError: number=-19 must be a positive integer\r\n    >>> is_happy_number(19.1)\r\n    Traceback (most recent call last):\r\n        ...\r\n    ValueError: number=19.1 must be a positive integer\r\n    >>> is_happy_number(\"happy\")\r\n    Traceback (most recent call last):\r\n        ...\r\n    ValueError: number='happy' must be a positive integer\r\n    \"\"\"\r\n    if not isinstance(number, int) or number <= 0:\r\n        msg = f\"{number=} must be a positive integer\"\r\n        raise ValueError(msg)\r\n\r\n    seen = set()\r\n    while number != 1 and number not in seen:\r\n        seen.add(number)\r\n        number = sum(int(digit) ** 2 for digit in str(number))\r\n    return number == 1\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    import doctest\r\n\r\n    doctest.testmod()\r\n","sourceCodeStart":18,"sourceCodeEnd":49,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/maths/special_numbers/happy_number.py#L18-L49","documentation":"Raised by is_happy_number() in maths/special_numbers/happy_number.py when number is not an int OR is <= 0 — both conditions share one check and one ValueError (unlike sibling functions that split TypeError/ValueError). The happy-number loop repeatedly sums squared digits, requiring a positive integer; str(number) digit iteration and set-cycle detection assume it. The f-string uses {number=} so the message shows e.g. \"number=-19 must be a positive integer\" or \"number='happy'\".","triggerScenarios":"Calling is_happy_number(-19), is_happy_number(0), is_happy_number(19.1), or is_happy_number('happy'). Any non-int (including floats and strings) or any int <= 0 raises. Note the doctest labels 19.1 and 'happy' as ValueError, not TypeError — plan exception handling accordingly.","commonSituations":"Unparsed user input passed straight through; float division results; 0 from empty-count defaults. Since one ValueError covers both bad type and bad range, a single except clause suffices — but you cannot distinguish cause from the exception alone.","solutions":["Validate early: if not isinstance(n, int) or n <= 0: reject input before calling","Convert numeric strings: is_happy_number(int(user_input)) with try/except around the conversion","Use floor division instead of true division when computing the argument"],"exampleFix":"# before\nis_happy_number(input('n: '))  # str -> ValueError\n\n# after\nn = int(input('n: '))\nif n > 0:\n    print(is_happy_number(n))","handlingStrategy":"validation","validationCode":"if isinstance(number, int) and not isinstance(number, bool) and number > 0:\n    print(is_happy_number(number))\nelse:\n    print('number must be a positive integer')","typeGuard":"def is_positive_int(value: object) -> bool:\n    return isinstance(value, int) and not isinstance(value, bool) and value > 0","tryCatchPattern":"try:\n    is_happy_number(number)\nexcept ValueError as e:\n    # single ValueError covers both bad type and <= 0\n    logger.warning('rejected input: %s', e)","preventionTips":["Parse user input with int() inside its own try/except before calling","One except ValueError covers floats, strings, 0, and negatives here","Never pass raw input() results to math functions"],"tags":["python","math","number-theory","validation","value-error"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}