{"record":{"id":"8e09c2fea0a00fd3","repo":"donnemartin/interactive-coding-challenges","slug":"num-cannot-be-negative","errorCode":null,"errorMessage":"num cannot be negative","messagePattern":"num cannot be negative","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"math_probability/add_digits/add_digits_solution.ipynb","lineNumber":101,"sourceCode":"   \"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\",\n    \"            return 0\\n\",\n    \"        elif num % 9 == 0:\\n\",","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/math_probability/add_digits/add_digits_solution.ipynb#L83-L119","documentation":"Solution.add_digits raises ValueError('num cannot be negative') because digit extraction via % and // does not represent negative numbers meaningfully in this implementation. The guard runs after the None check, so negative input is explicitly rejected rather than looping forever or producing wrong digit sums.","triggerScenarios":"Calling add_digits(-5), add_digits(-100), or passing a computed value that can go negative (e.g. a difference or delta) without clamping.","commonSituations":"Reusing the routine on differences/offsets that dip below zero; feeding raw signed integers from financial or sensor data; porting code that assumed abs() was applied upstream.","solutions":["Pass abs(num) if the sign is irrelevant to your use case","Clamp or validate at the boundary: reject negatives before calling add_digits","Catch ValueError when negatives are expected but should be skipped"],"exampleFix":"// before\nresult = solution.add_digits(delta)  # ValueError if delta < 0\n// after\nresult = solution.add_digits(abs(delta))","handlingStrategy":"validation","validationCode":"num = abs(num) if allow_negative else num\nif num < 0:\n    raise ValueError('num must be non-negative')\nsolution.add_digits(num)","typeGuard":"def is_non_negative_int(num) -> bool:\n    return isinstance(num, int) and num >= 0","tryCatchPattern":"try:\n    result = solution.add_digits(num)\nexcept ValueError:\n    result = solution.add_digits(abs(num))","preventionTips":["Apply abs() when digit sums of magnitudes are acceptable","Validate ranges of computed deltas before feeding them to digit routines"],"tags":["math","digits","validation","python"],"backgroundTag":"invalid-argument-value","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}