Skip to main content

Fix TypeError in Python

Error Reference

TypeError

TypeErrors arise when an operation receives a value of the wrong type. Here's how to interpret the message and fix it.

Read the message

The message names both types involved — read it before touching the code. The classic string/number mix:

age = input('Age: ')   # input() always returns a str
print(age + 1)
# TypeError: can only concatenate str (not "int") to str

print(1 + age)
# TypeError: unsupported operand type(s) for +: 'int' and 'str'

Same bug, two messages, depending on which operand comes first. Fix it by deciding what you actually want:

print(int(age) + 1)          # arithmetic: convert the string to int
print('age: ' + str(30)) # concatenation: convert the number to str
print(f'age: {30 + 1}') # f-strings format anything — usually the cleanest

Calls gone wrong

Argument mismatches produce very literal messages:

def greet(name):
print(f'Hello, {name}')

greet()
# TypeError: greet() missing 1 required positional argument: 'name'

greet(names='Ada')
# TypeError: greet() got an unexpected keyword argument 'names'

The first means you passed too few arguments; the second means a keyword doesn't match any parameter name (often a typo — names vs name).

Calling something that isn't callable is also a TypeError, usually caused by overwriting a function or forgetting an operator:

result = 5
result() # TypeError: 'int' object is not callable

A frequent variant: naming a variable list or print, which shadows the built-in for the rest of the program.

When None sneaks in

Many TypeErrors aren't about the value you see — they're about a None that came from a function you didn't check:

def find_user(users, name):
for user in users:
if user['name'] == name:
return user
# falls off the end -> returns None

user = find_user([], 'ada')
print(user['name'])
# TypeError: 'NoneType' object is not subscriptable

The error points at the subscript, but the bug is upstream: the function returned None. A special case that catches everyone once — methods that mutate in place return None:

numbers = [3, 1, 2]
numbers = numbers.sort() # sort() sorts in place and returns None
print(numbers[0])
# TypeError: 'NoneType' object is not subscriptable

Fix: either numbers.sort() on its own line, or numbers = sorted(numbers) if you want a new list.

Unhashable types

Dictionary keys and set members must be hashable — lists aren't, because they can change:

locations = {[48.85, 2.35]: 'Paris'}
# TypeError: unhashable type: 'list'

Use an immutable tuple instead:

locations = {(48.85, 2.35): 'Paris'}
print(locations[(48.85, 2.35)]) # Paris

The same applies to sets ({[1, 2]} fails) and to using a dict or set itself as a key.

Validation

  • Use isinstance checks for defensive programming.
  • Provide helpful errors: raise TypeError(f"expected str, got {type(value).__name__}").
  • Add type hints so linters catch mistakes earlier — a checker flags numbers = numbers.sort() before you ever run it.
def normalize(name):
if not isinstance(name, str):
raise TypeError(f'expected str, got {type(name).__name__}')
return name.strip().lower()

Frequently Asked Questions

What is the difference between TypeError and ValueError?

TypeError means the type itself is wrong for the operation — no value of that type could work, like len(42) or '1' + 1. ValueError means the type is acceptable but this particular value is not, like int('abc'): int() takes strings, just not that one. Rule of thumb: could some other value of the same type have succeeded? Then it's a ValueError.

len(42)      # TypeError: object of type 'int' has no len()
int('abc') # ValueError: invalid literal for int() with base 10: 'abc'

Why do I get "'NoneType' object is not subscriptable" (or has no attribute)?

Some expression you indexed or dotted into evaluated to None. Usually a function returned None — either it has a code path with no return statement, or it's an in-place method like list.sort(), list.reverse(), or random.shuffle(), which mutate their argument and deliberately return None. Track the None to its source rather than guarding the crash site.

numbers = [3, 1, 2]
numbers.sort() # correct: mutate, don't reassign
numbers = sorted(numbers) # or: build a new sorted list

Next up in your learning path