{"record":{"id":"d9e409241506c2fe","repo":"donnemartin/interactive-coding-challenges","slug":"str1-or-str2-cannot-be-none","errorCode":null,"errorMessage":"str1 or str2 cannot be None","messagePattern":"str1 or str2 cannot be None","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"arrays_strings/str_diff/str_diff_solution.ipynb","lineNumber":103,"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 find_diff(self, str1, str2):\\n\",\n    \"        if str1 is None or str2 is None:\\n\",\n    \"            raise TypeError('str1 or str2 cannot be None')\\n\",\n    \"        seen = {}\\n\",\n    \"        for char in str1:\\n\",\n    \"            if char in seen:\\n\",\n    \"                seen[char] += 1\\n\",\n    \"            else:\\n\",\n    \"                seen[char] = 1\\n\",\n    \"        for char in str2:\\n\",\n    \"            try:\\n\",\n    \"                seen[char] -= 1\\n\",\n    \"            except KeyError:\\n\",\n    \"                return char\\n\",\n    \"            if seen[char] < 0:\\n\",\n    \"                return char\\n\",\n    \"        for char, count in seen.items():\\n\",\n    \"            return char\\n\",\n    \"\\n\",\n    \"    def find_diff_xor(self, str1, str2):\\n\",\n    \"        if str1 is None or str2 is None:\\n\",","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/arrays_strings/str_diff/str_diff_solution.ipynb#L85-L121","documentation":"Raised by Solution.find_diff when str1 or str2 is None. The algorithm counts characters across both strings to find the extra char, so both must be actual strings. The guard fails fast with TypeError instead of a confusing iteration error.","triggerScenarios":"Calling find_diff(None, s) or find_diff(s, None); passing values from optional fields or unvalidated input.","commonSituations":"Comparing user-supplied strings where one side is optional; diffing file contents when one read returned None; API params forwarded without validation.","solutions":["Coerce to empty string when None: find_diff(s1 or '', s2 or '') if empty-vs-full is meaningful for you","Validate both inputs are str at the request boundary","Skip the diff entirely when either side is missing"],"exampleFix":"# before\nSolution().find_diff(old, new)  # old may be None\n\n# after\nif old is not None and new is not None:\n    Solution().find_diff(old, new)","handlingStrategy":"validation","validationCode":"if str1 is not None and str2 is not None:\n    Solution().find_diff(str1, str2)","typeGuard":"def is_diffable(s) -> bool:\n    return isinstance(s, str)","tryCatchPattern":"try:\n    Solution().find_diff(str1, str2)\nexcept TypeError:\n    return None  # missing input, no diff","preventionTips":["Validate both strings at the request boundary","Skip diffing when either side is missing rather than defaulting silently"],"tags":["string-diff","none-check","typeerror","validation"],"backgroundTag":"none-argument-rejected","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}