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.

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.

Appendix: 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)