{"record":{"id":"ce824aae052bd24c","repo":"donnemartin/interactive-coding-challenges","slug":"neighbor-cannot-be-none-ce824a","errorCode":null,"errorMessage":"neighbor cannot be None","messagePattern":"neighbor cannot be None","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"graphs_trees/graph/graph_solution.ipynb","lineNumber":203,"sourceCode":"    \"        self.adj_nodes = {}  # Key = key, val = Node\\n\",\n    \"        self.adj_weights = {}  # Key = key, val = weight\\n\",\n    \"\\n\",\n    \"    def __repr__(self):\\n\",\n    \"        return str(self.key)\\n\",\n    \"\\n\",\n    \"    def __lt__(self, other):\\n\",\n    \"        return self.key < other.key\\n\",\n    \"\\n\",\n    \"    def add_neighbor(self, neighbor, weight=0):\\n\",\n    \"        if neighbor is None or weight is None:\\n\",\n    \"            raise TypeError('neighbor or weight cannot be None')\\n\",\n    \"        neighbor.incoming_edges += 1\\n\",\n    \"        self.adj_weights[neighbor.key] = weight\\n\",\n    \"        self.adj_nodes[neighbor.key] = neighbor\\n\",\n    \"\\n\",\n    \"    def remove_neighbor(self, neighbor):\\n\",\n    \"        if neighbor is None:\\n\",\n    \"            raise TypeError('neighbor cannot be None')\\n\",\n    \"        if neighbor.key not in self.adj_nodes:\\n\",\n    \"            raise KeyError('neighbor not found')\\n\",\n    \"        neighbor.incoming_edges -= 1\\n\",\n    \"        del self.adj_weights[neighbor.key]\\n\",\n    \"        del self.adj_nodes[neighbor.key]\\n\",\n    \"\\n\",\n    \"\\n\",\n    \"class Graph:\\n\",\n    \"\\n\",\n    \"    def __init__(self):\\n\",\n    \"        self.nodes = {}  # Key = key, val = Node\\n\",\n    \"\\n\",\n    \"    def add_node(self, key):\\n\",\n    \"        if key is None:\\n\",\n    \"            raise TypeError('key cannot be None')\\n\",\n    \"        if key not in self.nodes:\\n\",\n    \"            self.nodes[key] = Node(key)\\n\",\n    \"        return self.nodes[key]\\n\",","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/graphs_trees/graph/graph_solution.ipynb#L185-L221","documentation":"Raised by Node.remove_neighbor(neighbor) in graph_solution.ipynb when neighbor is None. The method dereferences neighbor.key to look up and delete entries in adj_weights and adj_nodes, so a None neighbor would crash with AttributeError; the guard converts that into an explicit TypeError.","triggerScenarios":"Calling remove_neighbor(None) directly, or removing an edge where the destination node was never created (variable still None). Also hit when iterating a list of neighbors that contains None entries from malformed graph construction.","commonSituations":"Tearing down edges from untrusted datasets; test code that removes a neighbor it never added; refactor where the node variable name holds None after a failed lookup in self.nodes.","solutions":["Check the neighbor object is not None before calling remove_neighbor","Verify the node exists via graph.nodes.get(key) and skip when the lookup returns None","Sanitize adjacency lists at graph-build time so None nodes never enter the structure"],"exampleFix":"# before\nnode.remove_neighbor(maybe_none)  # TypeError\n\n# after\nif maybe_none is not None:\n    node.remove_neighbor(maybe_none)","handlingStrategy":"validation","validationCode":"if neighbor is not None:\n    node.remove_neighbor(neighbor)","typeGuard":"def is_removable(node, neighbor):\n    return neighbor is not None and neighbor.key in node.adj_nodes","tryCatchPattern":"try:\n    node.remove_neighbor(neighbor)\nexcept TypeError:\n    pass  # nothing to remove\nexcept KeyError as e:\n    if 'neighbor not found' in str(e):\n        pass  # already removed\n    else:\n        raise","preventionTips":["Guard both None and key-in-adj_nodes before removing","Keep a single source of truth for edge existence instead of manual dual-direction removals"],"tags":["python","graph","none-check","edge-removal"],"backgroundTag":"none-argument-validation","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}