Debugging — Python Error Guide

KeyError —
The dictionary hash lookup came up empty.

You asked a dictionary for a key that doesn't exist in it. It's the dictionary equivalent of IndexError — same underlying idea, "this position doesn't exist," just for hash-based lookup instead of a sequence position. Watch the lookup fail on LearnBug and see exactly which key was missing.

KeyErrorException type
.get()Safe alternative
PythonLanguage

What is KeyError?

Python raises KeyError when you access my_dict[key] with a key that isn't present in the dictionary. Unlike a list, a dictionary has no concept of "out of range" — it either has the exact key you asked for, or it doesn't, with no partial match or nearby fallback.

Why visualization helps

The traceback names the missing key, but not always why your code assumed it would be there — was the dictionary built from unreliable external data, or is a key genuinely optional? LearnBug shows the dictionary's actual keys at the moment of the lookup, right next to the key you're asking for, so the mismatch is visible immediately.

LearnBug — the dictionary's actual keys next to the failed lookup
🖼 Add a LearnBug screenshot here
What Causes It

Three ways a key ends up missing

The key genuinely isn't there

An optional field — like "email" on a user that never provided one — assumed to always exist, when it's actually sometimes absent by design.

Optional data

Typo or case mismatch in the key

Dictionary keys are matched exactly — "Email" and "email" are different keys, and "email " with a trailing space is different from both.

Exact match required

Counting/grouping into a dict without initializing first

Incrementing counts[word] += 1 on the first time a word appears crashes, because that key hasn't been set to a starting value yet.

Uninitialized key
Walkthrough

user["email"] on a dict without that key

1

user = {"name": "Alex", "age": 30} — only two keys exist

The dictionary was built with exactly two key-value pairs. There is no "email" key anywhere in it — not empty, not None, simply not present.

name: "Alex"
age: 30
Keys in user: name, age — that's the complete list
2

user["email"] — Python does a hash lookup for exactly "email"

Python computes a hash of the key "email" and checks if that hash exists in the dictionary's internal hash table. It doesn't — there's no near match, no fuzzy lookup.

"email"not found
Lookup for "email": not in dictionary
3

The [] lookup raises KeyError immediately, naming the missing key

Square-bracket access on a dictionary always raises if the key is missing — there's no default return value, unlike the .get() method.

Result: KeyError: 'email'

Code Example

The broken code, and the traceback it produces

PythonBroken — "email" was never added
user = {"name": "Alex", "age": 30}
print(user["email"])
TracebackWhat Python actually prints
Traceback (most recent call last):
  File "user.py", line 2, in <module>
    print(user["email"])
               ~~~~^^^^^^^^^^
KeyError: 'email'
The Fix

Use .get() with a default, or check first

PythonFixed — two safe approaches
user = {"name": "Alex", "age": 30}

# Fix 1: .get() returns None (or a custom default) instead of raising
email = user.get("email", "no email on file")
print(email)

# Fix 2: check membership before accessing
if "email" in user:
    print(user["email"])
else:
    print("no email on file")

Quick Reference

Error classKeyErrorRaised when a dictionary key doesn't exist and is accessed with []
Typical causeAssuming an optional key existsOften from external/user data where a field isn't guaranteed to be present
Fix patterndict.get(key, default)Returns a fallback value instead of raising when the key is missing
For counting/groupingcollections.defaultdictAuto-initializes missing keys to a default (like 0 or []) on first access

Frequently asked questions

What's the difference between dict[key] and dict.get(key)?

dict[key] raises KeyError if the key is missing. dict.get(key) returns None instead (or a custom default you pass as a second argument), never raising. Use [] when the key genuinely must exist and its absence is a bug worth knowing about immediately; use .get() when a missing key is a normal, expected case.

What is defaultdict and when should I use it?

collections.defaultdict(int) creates a dictionary where accessing a missing key automatically creates it with a default value (0 for int, an empty list for list, etc.) instead of raising KeyError. It's ideal for counting or grouping patterns — counts[word] += 1 just works even the first time word appears.

Why does the traceback show the key with quotes, like 'email'?

Python's KeyError message includes the actual key value (using repr()), which is genuinely useful — it tells you exactly which key was missing, not just that some key was missing. Compare this to a generic "key not found" message, which wouldn't tell you whether it was a typo, a case mismatch, or a truly absent field.

Does KeyError apply to sets too?

No — sets don't support key-based lookup at all (there's no my_set[x] syntax), so KeyError doesn't apply to them. Removing a missing element from a set with .remove() raises a different error, KeyError as well actually, since set.remove() specifically reuses it — but membership checks with in never raise on either sets or dicts.

Watch the dictionary lookup fail, and see the actual keys

Paste your code into LearnBug and see exactly which key was missing.

Open Playground →