donnemartin/interactive-coding-challenges · error · TypeError

graph cannot be None

Error message

graph cannot be None

What it means

Raised by ShortestPath.__init__(graph) in graph_shortest_path_solution.ipynb when graph is None. The constructor immediately iterates graph.nodes to seed previous/path_weight and fill the priority queue, so a None graph would crash with AttributeError; the guard raises TypeError('graph cannot be None') instead.

Source

Thrown at graphs_trees/graph_shortest_path/graph_shortest_path_solution.ipynb:185

   "outputs": [],
   "source": [
    "%run ../graph/graph.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "\n",
    "\n",
    "class ShortestPath(object):\n",
    "\n",
    "    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",

View on GitHub (pinned to 358f2cc604)

Solutions

  1. Ensure the Graph is constructed and populated before creating ShortestPath
  2. If using a builder/factory, make it raise or return a valid empty Graph rather than None
  3. Guard: if graph is None: skip or construct a new Graph() before instantiating ShortestPath

Example fix

# before
sp = ShortestPath(build_graph(data))  # TypeError if build_graph returns None

# after
g = build_graph(data)
if g is None:
    g = Graph()
sp = ShortestPath(g)
Defensive patterns

Strategy: validation

Validate before calling

if graph is not None:
    sp = ShortestPath(graph)
else:
    graph = Graph()  # or raise your own clearer error

Type guard

def is_usable_graph(graph):
    return graph is not None and hasattr(graph, 'nodes') and isinstance(graph.nodes, dict)

Try / catch

try:
    sp = ShortestPath(graph)
except TypeError as e:
    if 'graph cannot be None' in str(e):
        raise RuntimeError('graph construction failed upstream') from e
    raise

Prevention

When it happens

Trigger: Constructing ShortestPath(None); passing a variable holding None because the Graph was never instantiated or a builder function returned None on failure; conditionally creating the graph in one branch and using it in another.

Common situations: DI/test setups where the graph fixture failed to build; factory functions that return None on error whose result is passed straight through; refactoring that moved Graph construction after ShortestPath creation.

Related errors


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