donnemartin/interactive-coding-challenges · error · KeyError

neighbor not found

Error message

neighbor not found

What it means

Raised by Node.remove_neighbor when the neighbor's key is not present in this node's adjacency maps (adj_nodes/adj_weights). It prevents KeyError on the del statements and signals that no edge exists between the two nodes. Callers must ensure the edge was added before removing it.

Source

Thrown at graphs_trees/graph/graph.py:37

    def __repr__(self):
        return str(self.key)

    def __lt__(self, other):
        return self.key < other.key

    def add_neighbor(self, neighbor, weight=0):
        if neighbor is None or weight is None:
            raise TypeError('neighbor or weight cannot be None')
        neighbor.incoming_edges += 1
        self.adj_weights[neighbor.key] = weight
        self.adj_nodes[neighbor.key] = neighbor

    def remove_neighbor(self, neighbor):
        if neighbor is None:
            raise TypeError('neighbor cannot be None')
        if neighbor.key not in self.adj_nodes:
            raise KeyError('neighbor not found')
        neighbor.incoming_edges -= 1
        del self.adj_weights[neighbor.key]
        del self.adj_nodes[neighbor.key]


class Graph:

    def __init__(self):
        self.nodes = {}  # Key = key, val = Node

    def add_node(self, key):
        if key is None:
            raise TypeError('key cannot be None')
        if key not in self.nodes:
            self.nodes[key] = Node(key)
        return self.nodes[key]

    def add_edge(self, source_key, dest_key, weight=0):

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Guard with a membership check: if neighbor.key in node.adj_nodes before removing
  2. Track added edges at the application level to prevent double removal
  3. Catch KeyError as a signal the edge is already absent and treat as no-op

Example fix

# before
node.remove_neighbor(other)  # KeyError if no edge

# after
if other.key in node.adj_nodes:
    node.remove_neighbor(other)
Defensive patterns

Strategy: type-guard

Validate before calling

if neighbor.key in node.adj_nodes:
    node.remove_neighbor(neighbor)

Type guard

def edge_exists(node, neighbor) -> bool:
    return neighbor is not None and neighbor.key in node.adj_nodes

Try / catch

try:
    node.remove_neighbor(neighbor)
except KeyError:
    pass  # edge already absent, idempotent

Prevention

When it happens

Trigger: Calling remove_neighbor for a node never connected via add_neighbor/add_edge; removing the same edge twice; removing after the edge was already deleted.

Common situations: Double-remove bugs in cleanup code; attempting remove_edge on a graph where the edge was never added; race between checking and removing an edge.

Related errors


AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28). Data as JSON: /api/errors/f29a0b4ae657a3bb. Report an issue: GitHub.