{"record":{"id":"0be17f883f62385a","repo":"TheAlgorithms/Python","slug":"node-not-found","errorCode":null,"errorMessage":"Node not found","messagePattern":"Node not found","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"data_structures/linked_list/doubly_linked_list_two.py","lineNumber":139,"sourceCode":"    def insert_at_position(self, position: int, value: DataType) -> None:\n        current_position = 1\n        new_node = Node(value)\n        node = self.head\n        while node:\n            if current_position == position:\n                self.insert_before_node(node, new_node)\n                return\n            current_position += 1\n            node = node.next\n        self.set_tail(new_node)\n\n    def get_node(self, item: DataType) -> Node:\n        node = self.head\n        while node:\n            if node.data == item:\n                return node\n            node = node.next\n        raise Exception(\"Node not found\")\n\n    def delete_value(self, value):\n        if (node := self.get_node(value)) is not None:\n            if node == self.head:\n                self.head = self.head.next\n\n            if node == self.tail:\n                self.tail = self.tail.previous\n\n            self.remove_node_pointers(node)\n\n    @staticmethod\n    def remove_node_pointers(node: Node) -> None:\n        if node.next:\n            node.next.previous = node.previous\n\n        if node.previous:\n            node.previous.next = node.next","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/data_structures/linked_list/doubly_linked_list_two.py#L121-L157","documentation":"DoublyLinkedListTwo.get_node raises a generic Exception('Node not found') after walking from head to the end without matching item. Every consumer of get_node inherits this, notably delete_value, which despite its walrus 'if (node := self.get_node(value)) is not None' check can never reach the None branch — get_node raises instead of returning None.","triggerScenarios":"delete_value(v) or get_node(v) where no node's data == v; searching with the wrong type (str vs int); searching after the node was already unlinked by a prior delete.","commonSituations":"Caller assumes delete_value is a silent no-op for missing values (the walrus suggests a None check that never triggers); batch removals where a value occurs zero times; deserialized data with type drift.","solutions":["Wrap get_node/delete_value calls in try/except Exception and match on message 'Node not found' (generic Exception forces message matching).","Pre-verify the value exists by traversing or maintaining a set of current values before calling delete_value.","Subclass and override get_node to return None instead, which makes the existing 'is not None' check in delete_value work as designed."],"exampleFix":"# before\nlinked.delete_value(maybe_absent)  # Exception: Node not found\n# after\ntry:\n    linked.delete_value(maybe_absent)\nexcept Exception as e:\n    if 'Node not found' not in str(e):\n        raise","handlingStrategy":"try-catch","validationCode":"# pre-walk to confirm existence\ncur = dll.head\nexists = False\nwhile cur:\n    if cur.data == value:\n        exists = True\n        break\n    cur = cur.next\nif exists:\n    dll.delete_value(value)","typeGuard":null,"tryCatchPattern":"try:\n    dll.delete_value(value)\nexcept Exception as e:\n    if 'Node not found' not in str(e):\n        raise","preventionTips":["Do not trust the 'is not None' walrus in delete_value — get_node raises instead of returning None.","Generic Exception forces message matching; isolate it to this one call.","Keep a parallel set of contained values if you delete by value frequently."],"tags":["linked-list","lookup-failure","generic-exception","delete"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}