{"record":{"id":"66f571d33a8a6618","repo":"donnemartin/interactive-coding-challenges","slug":"root-cannot-be-none","errorCode":null,"errorMessage":"root cannot be None","messagePattern":"root cannot be None","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"graphs_trees/bst_second_largest/bst_second_largest_solution.ipynb","lineNumber":158,"sourceCode":"    \"\\n\",\n    \"    def _find_second_largest(self, node):\\n\",\n    \"        if node.right is not None:\\n\",\n    \"            if node.right.left is not None or node.right.right is not None:\\n\",\n    \"                return self._find_second_largest(node.right)\\n\",\n    \"            else:\\n\",\n    \"                return node\\n\",\n    \"        else:\\n\",\n    \"            return self._find_right_most_node(node.left)\\n\",\n    \"\\n\",\n    \"    def _find_right_most_node(self, node):\\n\",\n    \"        if node.right is not None:\\n\",\n    \"            return self._find_right_most_node(node.right)\\n\",\n    \"        else:\\n\",\n    \"            return node\\n\",\n    \"\\n\",\n    \"    def find_second_largest(self):\\n\",\n    \"        if self.root is None:\\n\",\n    \"            raise TypeError('root cannot be None')\\n\",\n    \"        if self.root.right is None and self.root.left is None:\\n\",\n    \"            raise ValueError('root must have at least one child')\\n\",\n    \"        return self._find_second_largest(self.root)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Unit Test\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/graphs_trees/bst_second_largest/bst_second_largest_solution.ipynb#L140-L176","documentation":"Bst.find_second_largest raises TypeError('root cannot be None') when called on an empty tree (self.root is None). Finding the second largest node requires at least one existing node, so an empty tree is an invalid state for this operation.","triggerScenarios":"tree = Bst(); tree.find_second_largest() — calling the method before any insert() has been made, or after all nodes were removed by a future delete operation.","commonSituations":"Running queries on a freshly constructed tree, on a tree populated conditionally where the data path was empty, or ordering operations incorrectly (query before insert).","solutions":["Populate the tree with at least one insert() before calling find_second_largest()","Guard the call: if tree.root is None: handle empty-tree case","Return a sentinel (e.g. None) for empty trees by wrapping the call in your own method"],"exampleFix":"# before\nbst = Bst()\nsecond = bst.find_second_largest()  # empty tree\n\n# after\nbst = Bst()\nfor x in (10, 5, 20):\n    bst.insert(x)\nsecond = bst.find_second_largest() if bst.root else None","handlingStrategy":"validation","validationCode":"if bst.root is None:\n    return None  # or raise your own 'tree is empty' error\nbst.find_second_largest()","typeGuard":"def is_non_empty_tree(t) -> bool:\n    return t is not None and t.root is not None","tryCatchPattern":"try:\n    second = bst.find_second_largest()\nexcept TypeError as e:\n    if 'root cannot be None' in str(e):\n        second = None\n    else:\n        raise","preventionTips":["Check tree.root before order-statistic queries","Populate the tree before querying it","Wrap the API in an accessor returning None for empty trees"],"tags":["python","bst","tree","empty-state","type-error"],"backgroundTag":"empty-collection-operation","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}