FULL PYTHON FIX · 8 MIN READ
How to Fix 'NoneType' object is not subscriptable in Python
Square brackets fail when the value before them is None. Trace the lookup that produced None, handle the missing record explicitly, and test the edge cases.
Quick fix
Return a clear fallback only when the lookup actually returns None.
def customer_name(customers, customer_id):
record = customers.get(customer_id)
if record is None:
return 'Unknown customer'
return record.get('name', 'Unnamed customer')
customers = {7: {'name': 'Ada'}, 8: {}}
print(customer_name(customers, 7))
print(customer_name(customers, 8))
print(customer_name(customers, 42))Video guide: How to Fix 'NoneType' object is not subscriptable in Python
The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube
Jump to a chapter
Read the video transcript
Select a timestamp to watch that moment on YouTube.
- 00:00
A customer directory maps numeric IDs to small dictionaries. Customer seven has a name, but the code asks for customer forty-two. We use get to look up the record, then square brackets to read the name. Run the program exactly as written. The final line says that a NoneType object is not subscriptable. The brackets are where Python discovers the problem, but the important question is what value arrived before those brackets. Here get returned None because customer forty-two is absent. The variable record now refers to None, not a customer dictionary. Indexing None cannot produce a name.
- 00:40
This pattern often appears in longer code: a helper returns None for a miss, and several lines later another function treats the result as a dictionary or list. The traceback points to the later read, while the cause is the earlier return path. We will trace that path, decide what a missing customer should mean, and verify that an empty but present customer record is handled differently. This diagnostic prints the looked-up value and its type before we attempt to read a field. For seven, we have a dictionary containing Ada. For eight, we have an empty dictionary. For forty-two, we have None, whose type name is NoneType.
- 01:20
The empty dictionary and None both count as false in a Boolean condition, but they do not mean the same thing in this data model. Eight is a known customer record with no name field yet; forty-two is an unknown ID. If we write `if not record`, we collapse those two cases and may show the wrong message. Instead, we can test `record is None` for an absent lookup. There is one more distinction: if we indexed an empty dictionary with `record['name']`, Python would raise KeyError, not this NoneType TypeError. The diagnosis is therefore not merely to replace brackets with get everywhere. It is to identify which state we have and define what each state should produce.
- 02:03
A function that accidentally omits a return could produce the same NoneType error by a different path, so always inspect the actual upstream assignment. The repaired function expresses the data policy in two steps. First, ask whether the ID exists. In this directory, values are dictionaries, so a None result from get unambiguously means the ID is missing. We return Unknown customer before trying any brackets or dictionary methods on None. For a present record, use record dot get to read the name field with an explicit fallback for an incomplete record. Run the calls: seven returns Ada, eight returns Unnamed customer, and forty-two returns Unknown customer.
- 02:48
These are deliberately distinct messages. We could have chosen direct dictionary indexing and caught KeyError for a missing ID, but this lookup path is clear when an absent ID is expected. Do not fix the error by blindly replacing every None with an empty dictionary. That would hide the difference between a missing customer and an incomplete one. Also do not use `record or {}` unless merging those states is truly intended. The function contract tells future callers what each result means, and the code follows that contract. The tests cover every state that matters to this function. A present name returns its exact stored text.
- 03:29
A present empty record gets its own fallback. An absent ID gets a different fallback. If we had replaced `is None` with `if not record`, the test for customer eight would fail, revealing the lost distinction. Consider one limitation of this design: it assumes customer values are always dictionaries. If the directory could contain None as an intentional stored value, get would return None both for that value and for an absent key. Then key membership, such as `if customer_id not in customers`, or a unique sentinel object would be needed. State such assumptions explicitly when writing production code.
- 04:09
Also check whether the caller wants a string fallback or an exception; for some applications a missing record is a data problem that should not be hidden. The underlying lesson is about tracing a value, not memorizing an exception phrase. When Python says NoneType is not subscriptable, inspect what is directly before the square brackets, then walk backward to the lookup, return statement, or mutation that made it None. In the companion guide, your task is to write display name. The users dictionary contains ID one with the name Ada and ID two with an empty record. ID ninety-nine is absent.
- 04:49
Your function should return Ada, Unnamed user, and Unknown user in that order. Start by getting the record. Test explicitly whether it is None, and only then read the name from the present dictionary. The automatic checks test all three cases, so a one-case patch will not be enough. After passing them, try adding a name to the empty record and confirm the function now returns that stored name. Then imagine a helper that forgets to return a record on one branch. The same debugging process applies: inspect the value before indexing, then inspect each path that can produce that value. Distinguish TypeError from KeyError, because they point to different failures.
- 05:33
The related Dictionaries and Conditions lessons build the pieces used here. Run the broken snippet yourself and explain why the error appears at the brackets even though the missing key was requested on the previous line.
Index a missing record
A small customer directory maps numeric IDs to records. The code looks up customer 42 with dictionary.get() and then tries to read the name field. Run the example as written. The lookup returns None because that ID is absent, so the expression record['name'] tries to subscript None. The last traceback line reports TypeError: 'NoneType' object is not subscriptable.
The error points to the square-bracket expression, but the cause may be several lines earlier where a helper or lookup returned None. A missing dictionary key is one common path. A function that reaches the end without returning a value is another. Before changing brackets to a method call, identify the value before the brackets and the rule that produced it.
customers = {7: {'name': 'Ada'}}
record = customers.get(42)
print(record['name'])TypeError: 'NoneType' object is not subscriptableCheck the value before using brackets
Print repr(record) and its type immediately before indexing. A dictionary's get() method returns the requested value when a key exists and None by default when it does not. The print output in this example is None and NoneType. The brackets are appropriate for a dictionary record, but they cannot make a missing record appear. Trace the ID used in the lookup and whether the directory contains it.
Do not conflate a missing record with an empty record. An empty dictionary is false in a Boolean test, as is None, but they can mean different things: the first says an entry exists with no fields, while the second says no entry was found. Use `is None` if that distinction matters. Also distinguish this TypeError from KeyError: a present dictionary without a 'name' key raises KeyError when indexed. The fix must define both policies.
customers = {7: {'name': 'Ada'}, 8: {}}
for customer_id in [7, 8, 42]:
record = customers.get(customer_id)
print(customer_id, repr(record), type(record).__name__)7 {'name': 'Ada'} dict
8 {} dict
42 None NoneTypeHandle the absent record before indexing
Return a clear fallback only when the lookup actually returns None. For a present record, use record.get('name', 'Unnamed customer') so a record with no name follows a separate rule. The caller can now distinguish no such customer from an incomplete customer record. The code checks absence before brackets or dictionary methods are used on the lookup result.
Another valid design is to use direct indexing and catch KeyError for a missing ID. Which approach is clearer depends on whether absence is expected and how the application reports it. Do not replace a missing record with an empty dictionary without thinking: that merges two states and can hide data quality problems. Keep the return values documented so callers can present the right message.
def customer_name(customers, customer_id):
record = customers.get(customer_id)
if record is None:
return 'Unknown customer'
return record.get('name', 'Unnamed customer')
customers = {7: {'name': 'Ada'}, 8: {}}
print(customer_name(customers, 7))
print(customer_name(customers, 8))
print(customer_name(customers, 42))Ada
Unnamed customer
Unknown customercustomers = {8: {}}
record = customers.get(8)
print(record is None)
print(bool(record))False
FalseTest present, empty, and absent records
A repair is complete only after all three cases work. A normal entry should return its stored name. An empty dictionary at an existing ID should return the incomplete-record label. An absent ID should return the unknown-customer label. This catches a common shortcut such as `if not record`, which would incorrectly treat the empty dictionary as a missing ID.
If a lookup helper can return None as a legitimate stored value, dictionary.get() alone cannot distinguish that from an absent key. In that design, test key membership with `if customer_id not in customers` or use a dedicated sentinel. Our sample directory stores only dictionaries, so None unambiguously means missing. State that assumption in real code rather than letting it remain invisible.
def customer_name(customers, customer_id):
record = customers.get(customer_id)
if record is None:
return 'Unknown customer'
return record.get('name', 'Unnamed customer')
customers = {7: {'name': 'Ada'}, 8: {}}
assert customer_name(customers, 7) == 'Ada'
assert customer_name(customers, 8) == 'Unnamed customer'
assert customer_name(customers, 42) == 'Unknown customer'
print('all cases passed')all cases passed- The value before square brackets is None, not a dictionary or list.
- Trace the assignment or return path that produced None.
- Use an explicit absence check when empty containers have a different meaning.
Practice the fix
Write display_name(users, user_id). Return the stored name when the user exists, 'Unnamed user' for a present empty record, and 'Unknown user' for an absent ID. Test IDs 1, 2, and 99 against {1: {'name': 'Ada'}, 2: {}}.
Need a hint?
Call users.get(user_id), then test `record is None` before using record.get('name', 'Unnamed user'). An empty dict is a present record.
Python console
Ready to runEdit the code and run it in your browser. Examples above can be loaded with Try this example.
Does your code use input()? Add one value per line
Your output appears here.
Write your solution, then select Check practice.
Key takeaways
- 'NoneType' object is not subscriptable means the value before brackets evaluated to None.
- dict.get() returns None by default when the requested key is absent.
- Check `is None` before indexing when missing and empty records differ.
- Test present, incomplete, and absent data separately.