donnemartin/interactive-coding-challenges · error · TypeError
key cannot be None
Error message
key cannot be None
What it means
Raised by Graph.add_node(key) when key is None. Nodes are stored in the self.nodes dict keyed by key, and None is treated as 'no key provided' rather than a hashable identifier. The guard uses TypeError because the argument type/value is fundamentally unusable as a node key.
Source
Thrown at graphs_trees/graph/graph_solution.ipynb:218
"\n",
" def remove_neighbor(self, neighbor):\n",
" if neighbor is None:\n",
" raise TypeError('neighbor cannot be None')\n",
" if neighbor.key not in self.adj_nodes:\n",
" raise KeyError('neighbor not found')\n",
" neighbor.incoming_edges -= 1\n",
" 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)"View on GitHub (pinned to 358f2cc604)
Solutions
- Default missing keys to a real value or skip the record before calling add_node
- Use graph.nodes.get(key) lookups instead of None sentinels when threading values into add_node
- Add an assertion/validation layer over raw input data that rejects null keys early
Example fix
# before
graph.add_node(some_dict.get('id')) # None if missing -> TypeError
# after
key = some_dict.get('id')
if key is not None:
graph.add_node(key) Defensive patterns
Strategy: validation
Validate before calling
if key is not None:
graph.add_node(key) Type guard
def is_valid_key(key):
return key is not None Try / catch
try:
graph.add_node(key)
except TypeError:
skip_record(key) # or log and continue batch import Prevention
- Reject or default null key fields during data ingestion
- Avoid dict.get(key) results as direct node keys without a None check
When it happens
Trigger: Calling add_node(None); passing an optional variable that was never assigned; Graph.add_edge auto-invoking add_node(source_key) or add_node(dest_key) when one of those keys is None.
Common situations: Loading vertices from sparse JSON/DB rows where a key field is null; using None as a sentinel for 'missing node' and then feeding it into the graph; dict.get(key) returning None and being forwarded as a node key.
Related errors
- key cannot be None
- neighbor or weight cannot be None
- neighbor cannot be None
- graph cannot be None
- Input node keys cannot be None
AI-assisted analysis of donnemartin/interactive-coding-challenges@358f2cc604 (2026-08-28).
Data as JSON: /api/errors/702802100bdcb2b6.
Report an issue: GitHub.