donnemartin/interactive-coding-challenges · error · KeyError
Invalid key
Error message
Invalid key
What it means
Raised by Graph.add_edge(source_key, dest_key, weight) when source_key or dest_key is None. The method auto-creates missing nodes, but None is not an acceptable key, so it raises KeyError('Invalid key') rather than silently creating a None-keyed node. Note this fires before the None keys can flow into add_node.
Source
Thrown at graphs_trees/graph/graph_solution.ipynb:225
" del self.adj_weights[neighbor.key]\n",
" del self.adj_nodes[neighbor.key]\n",
"\n",
"\n",
"class Graph:\n",
"\n",
" def __init__(self):\n",
" self.nodes = {} # Key = key, val = Node\n",
"\n",
" def add_node(self, key):\n",
" if key is None:\n",
" raise TypeError('key cannot be None')\n",
" if key not in self.nodes:\n",
" self.nodes[key] = Node(key)\n",
" return self.nodes[key]\n",
"\n",
" def add_edge(self, source_key, dest_key, weight=0):\n",
" if source_key is None or dest_key is None:\n",
" raise KeyError('Invalid key')\n",
" if source_key not in self.nodes:\n",
" self.add_node(source_key)\n",
" if dest_key not in self.nodes:\n",
" self.add_node(dest_key)\n",
" self.nodes[source_key].add_neighbor(self.nodes[dest_key], weight)\n",
"\n",
" def add_undirected_edge(self, src_key, dst_key, weight=0):\n",
" if src_key is None or dst_key is None:\n",
" raise TypeError('key cannot be None')\n",
" self.add_edge(src_key, dst_key, weight)\n",
" self.add_edge(dst_key, src_key, weight)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],View on GitHub (pinned to 358f2cc604)
Solutions
- Validate both endpoint keys are non-None before calling add_edge
- Fix upstream data: fill or drop edges with null endpoints at load time
- If None means 'not found', use graph.nodes.get() and skip edge creation when it returns None
Example fix
# before
graph.add_edge(row['src'], row['dst']) # KeyError when a column is null
# after
if row['src'] is not None and row['dst'] is not None:
graph.add_edge(row['src'], row['dst']) Defensive patterns
Strategy: validation
Validate before calling
if source_key is not None and dest_key is not None:
graph.add_edge(source_key, dest_key, weight) Type guard
def is_valid_edge(src, dst):
return src is not None and dst is not None Try / catch
try:
graph.add_edge(src, dst, weight)
except KeyError as e:
if 'Invalid key' in str(e):
log_bad_edge(src, dst)
else:
raise Prevention
- Filter edges with null endpoints at load time
- Pass weight as a keyword argument to avoid positional mix-ups
When it happens
Trigger: Calling add_edge(None, 'b'), add_edge('a', None), or add_edge(x, y) where x/y came from a failed lookup like graph.nodes.get(missing) or a nullable data field.
Common situations: Building graphs from edge lists with null endpoint columns; passing variables that were never initialized because an earlier step failed silently; confusing None with the default weight parameter positionally (add_edge('a', None)).
Related errors
- neighbor not found
- Invalid start or end node key
- neighbor not found
- Invalid key
- neighbor or weight cannot be None
AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28).
Data as JSON: /api/errors/b158f5a8ded1bd96.
Report an issue: GitHub.