{"record":{"id":"2bf55368070d1f71","repo":"donnemartin/interactive-coding-challenges","slug":"input-node-keys-cannot-be-none","errorCode":null,"errorMessage":"Input node keys cannot be None","messagePattern":"Input node keys cannot be None","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"graphs_trees/graph_shortest_path/graph_shortest_path_solution.ipynb","lineNumber":201,"sourceCode":"    \"    def __init__(self, graph):\\n\",\n    \"        if graph is None:\\n\",\n    \"            raise TypeError('graph cannot be None')\\n\",\n    \"        self.graph = graph\\n\",\n    \"        self.previous = {}  # Key: node key, val: prev node key, shortest path\\n\",\n    \"        self.path_weight = {}  # Key: node key, val: weight, shortest path\\n\",\n    \"        self.remaining = PriorityQueue()  # Queue of node key, path weight\\n\",\n    \"        for key in self.graph.nodes.keys():\\n\",\n    \"            # Set each node's previous node key to None\\n\",\n    \"            # Set each node's shortest path weight to infinity\\n\",\n    \"            # Add each node's shortest path weight to the priority queue\\n\",\n    \"            self.previous[key] = None\\n\",\n    \"            self.path_weight[key] = sys.maxsize\\n\",\n    \"            self.remaining.insert(\\n\",\n    \"                PriorityQueueNode(key, self.path_weight[key]))\\n\",\n    \"\\n\",\n    \"    def find_shortest_path(self, start_node_key, end_node_key):\\n\",\n    \"        if start_node_key is None or end_node_key is None:\\n\",\n    \"            raise TypeError('Input node keys cannot be None')\\n\",\n    \"        if (start_node_key not in self.graph.nodes or\\n\",\n    \"                end_node_key not in self.graph.nodes):\\n\",\n    \"            raise ValueError('Invalid start or end node key')\\n\",\n    \"        # Set the start node's shortest path weight to 0\\n\",\n    \"        # and update the value in the priority queue\\n\",\n    \"        self.path_weight[start_node_key] = 0\\n\",\n    \"        self.remaining.decrease_key(start_node_key, 0)\\n\",\n    \"        while self.remaining:\\n\",\n    \"            # Extract the min node (node with minimum path weight)\\n\",\n    \"            # from the priority queue\\n\",\n    \"            min_node_key = self.remaining.extract_min().obj\\n\",\n    \"            min_node = self.graph.nodes[min_node_key]\\n\",\n    \"            # Loop through each adjacent node in the min node\\n\",\n    \"            for adj_key in min_node.adj_nodes.keys():\\n\",\n    \"                # Node's path:\\n\",\n    \"                # Adjacent node's edge weight + the min node's\\n\",\n    \"                # shortest path weight\\n\",\n    \"                new_weight = (min_node.adj_weights[adj_key] +\\n\",","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/donnemartin/interactive-coding-challenges/blob/358f2cc60426d5c4c3d7d580910eec9a7b393fa9/graphs_trees/graph_shortest_path/graph_shortest_path_solution.ipynb#L183-L219","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Validate both keys are non-None before calling find_shortest_path","Use graph.nodes.get(key) and handle None by choosing a valid default or erroring with your own message","Make start/end keys required (non-optional) in your calling code so None cannot propagate"],"exampleFix":"# before\nsp.find_shortest_path(start, end)  # TypeError if either is None\n\n# after\nif start is not None and end is not None:\n    sp.find_shortest_path(start, end)","handlingStrategy":"validation","validationCode":"if start_node_key is not None and end_node_key is not None:\n    sp.find_shortest_path(start_node_key, end_node_key)","typeGuard":"def are_valid_keys(*keys):\n    return all(k is not None for k in keys)","tryCatchPattern":"try:\n    sp.find_shortest_path(start, end)\nexcept TypeError:\n    skip_query(start, end)  # missing endpoint in input\nexcept ValueError:\n    handle_unknown_node(start, end)","preventionTips":["Make start/end keys required parameters in calling code","Never forward dict.get() results without a None check"],"tags":["python","graph","dijkstra","none-check"],"backgroundTag":"none-argument-validation","analyzedSha":"358f2cc60426d5c4c3d7d580910eec9a7b393fa9","analyzedAt":"2026-08-28T10:16:54.480Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}