Python KeyError: What It Means and How to Fix It
1Python KeyError: overview
A KeyError is raised when you use square brackets to ask a dictionary for a key it does not contain, like user["phone"] when there is no "phone" key.
Before this lesson: Python Dictionaries, Python Exceptions: try, except, else and finally
2Python KeyError: diagram
3Python KeyError: explained step by step
A dictionary finds values by key. Writing user["email"] tells Python "this key definitely exists". If it doesn't, Python won't make up a value. It raises a KeyError, and the message is simply the key it couldn't find, such as KeyError: 'phone'.
How to read the traceback
Traceback (most recent call last):
File "main.py", line 2, in <module>
print(user["phone"])
~~~~^^^^^^^^^
KeyError: 'phone'
The last line shows the exact key Python searched for, in quotes if it's a string. The line above it shows where the lookup happened, and the ^^^ marks the key inside the brackets. Now compare that key, character by character, with the keys the dictionary really has. print(list(user)) lists them. Watch out for capital letters, stray spaces and quotes: KeyError: 1 means you looked up the number 1, while KeyError: '1' means the string "1".
Common causes
- A typo or different capitalisation. Keys are case-sensitive:
"Email","email"and"email "are three different keys. - Data that doesn't always include the field. Records from JSON files, APIs and forms often leave out optional fields.
- A key that was never added, or was removed. Counting with
counts[word] += 1fails the first time a word appears, anddelorpop()remove keys your code may still read later. - The wrong key type. JSON object keys are always strings, so after
json.loads()you needdata["1"], notdata[1].
Fixes for reading values
user = {"name": "Asha", "email": "asha@example.com"}
print(user.get("phone")) # None instead of an error
print(user.get("phone", "not given")) # or your own default
if "email" in user: # check first
print("Email:", user["email"])
try:
print(user["Email"])
except KeyError as err:
print("Missing key:", err)
print("Real keys:", list(user))Fixes for building a dictionary
When you are filling a dictionary, let Python create missing keys for you:
from collections import defaultdict
words = ["red", "blue", "red", "green", "red"]
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1
print(counts)
by_length = {}
for w in words:
by_length.setdefault(len(w), []).append(w)
print(by_length)
by_letter = defaultdict(list)
for w in words:
by_letter[w[0]].append(w)
print(dict(by_letter))d.get(key, default)reads a value that may be missing.key in dlets you decide what to do before reading.d.setdefault(key, default)inserts the default only when the key is missing, then returns the value stored under that key.defaultdict(list)ordefaultdict(int)fills in missing keys automatically.try/except KeyErrorsuits a missing key that is rare and should be handled in one place.
Square brackets are still the right choice when a key must be there. If it's missing, a loud KeyError points you straight at the real bug instead of letting a silent default hide it.
Quick reference: Python KeyError
- Python Dictionary get() Method — `dict.get(key, default=None)` returns the value for `key` if it exists, otherwise `default` (which is `None` …
- Python Set remove() Method — `set.remove(element)` deletes the element from the set in place and returns `None`. If the element is **not**…
- Python Dictionary pop() Method — `dict.pop(key[, default])` removes `key` from the dictionary and returns its value. If the key is missing it …
- Python Dictionary setdefault() Method — `dict.setdefault(key, default=None)` returns the value for `key` if it exists; otherwise it stores `default` …
4Python KeyError: syntax
d[key] # KeyError if key is missing
d.get(key) # None if missing
d.get(key, default) # default if missing
key in d # True / False
d.setdefault(key, []) # add default if missing, return value
d.pop(key, None) # remove without a KeyError
from collections import defaultdict
counts = defaultdict(int) # missing keys start at 0
5Python KeyError: run the example
Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.
orders = [
{"id": 101, "customer": "Asha", "coupon": "SAVE10"},
{"id": 102, "customer": "Ben"},
{"id": 103, "customer": "Chen", "coupon": "FREESHIP"},
]
for order in orders:
try:
print(order["id"], "coupon:", order["coupon"])
except KeyError as err:
print(order["id"], "has no key", err)
for order in orders:
coupon = order.get("coupon", "none")
print(f"{order['customer']}: {coupon}")
print("Keys in order 102:", list(orders[1]))Expected output101 coupon: SAVE10
102 has no key 'coupon'
103 coupon: FREESHIP
Asha: SAVE10
Ben: none
Chen: FREESHIP
Keys in order 102: ['id', 'customer']
7Python KeyError: how the example works
Hover or tap a step to highlight its lines in the example above.
- Line 1-5A list of three order dictionaries, like records loaded from a JSON file. Order 102 has no
"coupon"key because it's an optional field. - Line 7-9The first loop reads
order["coupon"]with square brackets. That works for orders 101 and 103. - Line 10-11For order 102 the lookup raises KeyError. The
exceptblock catches it, anderrprints as the missing key:'coupon'. - Line 13-15The second loop uses
get("coupon", "none"), which never raises: it returns the coupon when it exists and the default"none"when it doesn't. - Line 17
list(orders[1])lists the keys a dictionary really has. It's the quickest way to see why a lookup failed.
8Python KeyError: common mistakes
The key's spelling or capitalisation doesn't match
✗ Wrong
stock = {"apples": 4, "pears": 0}
print(stock["Apples"])✓ Right
stock = {"apples": 4, "pears": 0}
item = "Apples"
print(stock[item.lower()])Keys are case-sensitive. Use the exact key, or store keys in lowercase and convert what you look up with .lower() (and .strip() for stray spaces).
Adding to a count before the key exists
✗ Wrong
votes = ["yes", "no", "yes"]
tally = {}
for v in votes:
tally[v] += 1✓ Right
votes = ["yes", "no", "yes"]
tally = {}
for v in votes:
tally[v] = tally.get(v, 0) + 1
print(tally)tally[v] += 1 has to read tally[v] first, and the first time a vote appears there is nothing to read. Start from 0 with get(), or use defaultdict(int).
Looking up a number when the keys are strings
✗ Wrong
import json
medals = json.loads('{"1": "gold", "2": "silver"}')
print(medals[1])✓ Right
import json
medals = json.loads('{"1": "gold", "2": "silver"}')
place = 1
print(medals[str(place)])JSON object keys are always strings, so the key is "1", not the number 1. Notice the message shows 1 without quotes. Convert the number with str().
9Python KeyError: exercises
Write your answer, then press Check. The checks run in your browser.
1. Price with a default
Write code Easy ✓ CompletedWrite get_price(menu, item) that returns the price of item from the dictionary menu, or 0 if the item isn't on the menu. It must never raise a KeyError.
def get_price(menu, item):
return menu.get(item, 0)
menu = {"tea": 2.5, "cake": 4.0}
print(get_price(menu, "tea"))
print(get_price(menu, "pizza"))
2. Predict get() and setdefault()
Predict the output Medium ✓ CompletedRead the code and type exactly what it will print. Then press Check to compare.
stock = {"pen": 3, "ink": 0}
print(stock.get("ink", 5))
print(stock.get("pad", 5))
print("pad" in stock)
stock.setdefault("pad", 10)
stock.setdefault("pen", 99)
print(stock)0
5
False
{'pen': 3, 'ink': 0, 'pad': 10}
2 more exercises → 4 more examples
Questions learners ask
How do I check if a key exists in a Python dictionary?
Use the in operator: if "email" in user: ... It returns True or False and never raises an error. Use not in for the opposite check. There is no need to call .keys(); key in d is the fastest and clearest way.
Should I use get() or try/except KeyError?
Use get(key, default) when a missing key is normal and a sensible default exists, like an optional coupon. Use try/except KeyError when a missing key is unusual and you want to handle it in one place. Use plain square brackets when the key must always be there, so a bug shows up immediately.
Why does my KeyError show a number, like KeyError: 0?
Python is showing the exact key it searched for: here the integer 0. Either the dictionary's keys are strings ("0"), which is always true for data loaded from JSON, or you treated a dictionary like a list and used a position. Print list(your_dict) to see the real keys.
Further reading
10Next lesson
Up nextPython IndexError: list index out of rangeAn IndexError happens when you ask a list, tuple or string for a position that doesn't exist, such as item 3 of a list …Related:
Python DictionariesPython Exceptions: try, except, else and finallyPython IndexError: list index out of rangeWorking with JSON in Python
← Python TypeError: What It Means and How to Fix It · All Errors and Exceptions lessons · Practise in the IDE