{"record":{"id":"5e1c05444d1de550","repo":"donnemartin/interactive-coding-challenges","slug":"cannot-have-a-none-input","errorCode":null,"errorMessage":"Cannot have a None input","messagePattern":"Cannot have a None input","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"recursion_dynamic/hanoi/hanoi_solution.ipynb","lineNumber":100,"sourceCode":"   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"%run ../../stacks_queues/stack/stack.py\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"class Hanoi(object):\\n\",\n    \"\\n\",\n    \"    def move_disks(self, num_disks, src, dest, buff):\\n\",\n    \"        if src is None or dest is None or buff is None:\\n\",\n    \"            raise TypeError('Cannot have a None input')\\n\",\n    \"        self._move_disks(num_disks, src, dest, buff)\\n\",\n    \"\\n\",\n    \"    def _move_disks(self, num_disks, src, dest, buff):\\n\",\n    \"        if num_disks == 0:\\n\",\n    \"            return\\n\",\n    \"        self.move_disks(num_disks - 1, src, buff, dest)\\n\",\n    \"        dest.push(src.pop())\\n\",\n    \"        self.move_disks(num_disks - 1, buff, dest, src)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Unit Test\\n\",\n    \"\\n\"\n   ]\n  },","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/recursion_dynamic/hanoi/hanoi_solution.ipynb#L82-L118","documentation":"Raised by Hanoi.move_disks when any of the src, dest, or buff tower arguments is None. It is an explicit input-validation guard at the top of the public API before the recursive _move_disks helper runs, because the algorithm assumes all three pegs are real stack-like objects. It exists to fail fast with a clear message instead of an opaque AttributeError deep in the recursion.","triggerScenarios":"Calling hanoi.move_disks(num_disks, None, dest, buff), or passing any peg as None, e.g. initializing tower objects where one failed to construct. The very first check in move_disks triggers before any recursion.","commonSituations":"Building the three stacks (source/destination/buffer) from user input or a config where one is missing; refactoring constructors so a peg defaults to None; unmarshalling data where a tower list is absent.","solutions":["Ensure all three tower arguments are initialized (e.g. dest = Stack(), buff = Stack()) before calling move_disks","If pegs may be absent, default them to empty Stack instances instead of None","Add a caller-side guard: if any peg is None, skip or report the call before invoking move_disks"],"exampleFix":"// before\nhanoi.move_disks(3, src, None, buff)\n// after\nbuff = Stack()\nhanoi.move_disks(3, src, dest, buff)","handlingStrategy":"validation","validationCode":"if src is None or dest is None or buff is None:\n    raise ValueError('all towers must be provided')\nhanoi.move_disks(n, src, dest, buff)","typeGuard":"def valid_towers(*towers):\n    return all(t is not None for t in towers)","tryCatchPattern":"try:\n    hanoi.move_disks(n, src, dest, buff)\nexcept TypeError as e:\n    if 'Cannot have a None input' in str(e):\n        # initialize missing towers and retry\n        ...","preventionTips":["Always construct all three Stack objects up front","Never default tower parameters to None"],"tags":["python","input-validation","typeerror","recursion","hanoi"],"backgroundTag":"none-argument-validation","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}