donnemartin/interactive-coding-challenges · error · TypeError

Input node keys cannot be None

Error message

Input node keys cannot be None

What it means

Raised by ShortestPath.find_shortest_path(start_node_key, end_node_key) when either key is None. The method indexes self.graph.nodes and self.path_weight with these keys; None would fail the membership check anyway, but the code distinguishes 'missing argument' (TypeError) from 'key not in graph' (ValueError) and raises TypeError for None inputs.

Source

Thrown at graphs_trees/graph_shortest_path/graph_shortest_path_solution.ipynb:201

    "    def __init__(self, graph):\n",
    "        if graph is None:\n",
    "            raise TypeError('graph cannot be None')\n",
    "        self.graph = graph\n",
    "        self.previous = {}  # Key: node key, val: prev node key, shortest path\n",
    "        self.path_weight = {}  # Key: node key, val: weight, shortest path\n",
    "        self.remaining = PriorityQueue()  # Queue of node key, path weight\n",
    "        for key in self.graph.nodes.keys():\n",
    "            # Set each node's previous node key to None\n",
    "            # Set each node's shortest path weight to infinity\n",
    "            # Add each node's shortest path weight to the priority queue\n",
    "            self.previous[key] = None\n",
    "            self.path_weight[key] = sys.maxsize\n",
    "            self.remaining.insert(\n",
    "                PriorityQueueNode(key, self.path_weight[key]))\n",
    "\n",
    "    def find_shortest_path(self, start_node_key, end_node_key):\n",
    "        if start_node_key is None or end_node_key is None:\n",
    "            raise TypeError('Input node keys cannot be None')\n",
    "        if (start_node_key not in self.graph.nodes or\n",
    "                end_node_key not in self.graph.nodes):\n",
    "            raise ValueError('Invalid start or end node key')\n",
    "        # Set the start node's shortest path weight to 0\n",
    "        # and update the value in the priority queue\n",
    "        self.path_weight[start_node_key] = 0\n",
    "        self.remaining.decrease_key(start_node_key, 0)\n",
    "        while self.remaining:\n",
    "            # Extract the min node (node with minimum path weight)\n",
    "            # from the priority queue\n",
    "            min_node_key = self.remaining.extract_min().obj\n",
    "            min_node = self.graph.nodes[min_node_key]\n",
    "            # Loop through each adjacent node in the min node\n",
    "            for adj_key in min_node.adj_nodes.keys():\n",
    "                # Node's path:\n",
    "                # Adjacent node's edge weight + the min node's\n",
    "                # shortest path weight\n",
    "                new_weight = (min_node.adj_weights[adj_key] +\n",

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Validate both keys are non-None before calling find_shortest_path
  2. Use graph.nodes.get(key) and handle None by choosing a valid default or erroring with your own message
  3. Make start/end keys required (non-optional) in your calling code so None cannot propagate

Example fix

# before
sp.find_shortest_path(start, end)  # TypeError if either is None

# after
if start is not None and end is not None:
    sp.find_shortest_path(start, end)
Defensive patterns

Strategy: validation

Validate before calling

if start_node_key is not None and end_node_key is not None:
    sp.find_shortest_path(start_node_key, end_node_key)

Type guard

def are_valid_keys(*keys):
    return all(k is not None for k in keys)

Try / catch

try:
    sp.find_shortest_path(start, end)
except TypeError:
    skip_query(start, end)  # missing endpoint in input
except ValueError:
    handle_unknown_node(start, end)

Prevention

When it happens

Trigger: Calling find_shortest_path(None, 'b') or find_shortest_path('a', None); passing keys obtained from dict.get() that returned None for missing entries; calling with uninitialized key variables.

Common situations: Looking up start/end keys from user input or config where a field is absent; threading graph.nodes.get(missing_key) results into the call; optional function parameters defaulting to None and forwarded without checks.

Related errors


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