{"record":{"id":"f7a463a8498187da","repo":"donnemartin/interactive-coding-challenges","slug":"num-cannot-be-none-f7a463","errorCode":null,"errorMessage":"num cannot be None","messagePattern":"num cannot be None","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"math_probability/add_digits/add_digits_solution.ipynb","lineNumber":99,"sourceCode":"  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Code\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"class Solution(object):\\n\",\n    \"\\n\",\n    \"    def add_digits(self, num):\\n\",\n    \"        if num is None:\\n\",\n    \"            raise TypeError('num cannot be None')\\n\",\n    \"        if num < 0:\\n\",\n    \"            raise ValueError('num cannot be negative')\\n\",\n    \"        digits = []\\n\",\n    \"        while num != 0:\\n\",\n    \"            digits.append(num % 10)\\n\",\n    \"            num //= 10\\n\",\n    \"        digits_sum = sum(digits)\\n\",\n    \"        if digits_sum >= 10:\\n\",\n    \"            return self.add_digits(digits_sum)\\n\",\n    \"        else:\\n\",\n    \"            return digits_sum\\n\",\n    \"\\n\",\n    \"    def add_digits_optimized(self, num):\\n\",\n    \"        if num is None:\\n\",\n    \"            raise TypeError('num cannot be None')\\n\",\n    \"        if num < 0:\\n\",\n    \"            raise ValueError('num cannot be negative')\\n\",\n    \"        if num == 0:\\n\",","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/math_probability/add_digits/add_digits_solution.ipynb#L81-L117","documentation":"Solution.add_digits raises TypeError('num cannot be None') because the digit-extraction loop (num % 10, num //= 10) requires an integer. The guard rejects None input before any arithmetic is attempted, keeping the failure message clear rather than a confusing TypeError about unsupported operand types.","triggerScenarios":"Calling add_digits(None), or passing a parsed value (str.isdigit-unchecked input, optional config field) that resolved to None.","commonSituations":"Processing unvalidated user or file input where a missing numeric field becomes None; test suites that include None as an edge case alongside negative and zero values.","solutions":["Validate and coerce input before the call: num = int(num) if num is not None else fail early","Check the data source producing None (missing field, failed parse)","Catch TypeError when None is a legitimate edge case in tests"],"exampleFix":"// before\nresult = solution.add_digits(value)  # TypeError if value is None\n// after\nif value is None:\n    raise ValueError('missing numeric input')\nresult = solution.add_digits(int(value))","handlingStrategy":"validation","validationCode":"if num is None or not isinstance(num, int):\n    raise ValueError('num must be an integer')\nsolution.add_digits(num)","typeGuard":"def is_int(num) -> bool:\n    return isinstance(num, int) and num is not None","tryCatchPattern":"try:\n    result = solution.add_digits(num)\nexcept TypeError:\n    result = None","preventionTips":["Coerce and validate numeric input at system boundaries","Include None in negative/zero edge-case tests to document behavior"],"tags":["math","digits","none-guard","python"],"backgroundTag":"none-argument-guard","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}