donnemartin/interactive-coding-challenges · error · TypeError

neighbor or weight cannot be None

Error message

neighbor or weight cannot be None

What it means

Raised by Node.add_neighbor when either neighbor or weight is None. The graph stores weights and node references in dicts keyed by neighbor.key, so None inputs would break those lookups. It guards the internal edge-bookkeeping used by add_edge.

Source

Thrown at graphs_trees/graph/graph.py:28

class Node:

    def __init__(self, key):
        self.key = key
        self.visit_state = State.unvisited
        self.incoming_edges = 0
        self.adj_nodes = {}  # Key = key, val = Node
        self.adj_weights = {}  # Key = key, val = weight

    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

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Call Graph.add_edge instead of Node.add_neighbor; it handles node creation
  2. Ensure weight is an int (default 0) and neighbor is a real Node instance
  3. Check for None before invoking when weight comes from external config

Example fix

# before
graph.nodes['a'].add_neighbor(graph.nodes['b'], None)

# after
graph.add_edge('a', 'b', weight=0)
Defensive patterns

Strategy: validation

Validate before calling

if neighbor is not None and weight is not None:
    node.add_neighbor(neighbor, weight)

Type guard

def valid_edge_parts(neighbor, weight) -> bool:
    return neighbor is not None and weight is not None and isinstance(weight, int)

Try / catch

try:
    node.add_neighbor(neighbor, weight)
except TypeError:
    log.warning('invalid edge parts, skipping')

Prevention

When it happens

Trigger: Calling node.add_neighbor(None) or node.add_neighbor(node, None); indirectly via Graph.add_edge(src, dst, weight=None).

Common situations: Passing a default weight parameter that was computed as None from config; calling the low-level Node API directly instead of Graph.add_edge.

Related errors


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