/errors/python/typeerror-unhashable-type-list
TypeError: unhashable type: 'list'
- tool
- Python
- exit code
- 1
- versions
- Python 3.x
- os
- any
TypeError: unhashable type: 'list' means a list was used where Python needs a hashable value: as a dictionary key, as a set member, or as an argument to a function that hashes its arguments. Lists are mutable, so they have no stable hash. Use a tuple instead, or move the list to the value side of the dictionary.
Reproduce it
cat > app.py <<'EOF'
d = {[1, 2]: "pair"}
EOF
python app.pyOutput · exit 1
Traceback (most recent call last):
File "/tmp/work/app.py", line 1, in <module>
d = {[1, 2]: "pair"}
^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'The same error appears for set([[1, 2], [3]]) and for {1, [2]}.
Fixes
cat > fix.py <<'EOF'
d = {(1, 2): "pair"} # tuple as key
print(d[(1, 2)])
rows = [[1, 2], [3], [1, 2]]
print(sorted(set(map(tuple, rows)))) # unique rows
print({frozenset([1, 2]): "unordered"}) # order does not matter
print({"pair": [1, 2]}) # list as value
EOF
python fix.pyOutput
pair
[(1, 2), (3,)]
{frozenset({1, 2}): 'unordered'}
{'pair': [1, 2]}| Type | Hashable |
|---|---|
| int, float, str, bytes, bool, None | yes |
| tuple, frozenset | yes, if all items are hashable |
| list, dict, set | no |
A tuple that contains a list is also unhashable: hash(([1], 2)) raises the same error.
Less obvious places
The error is not limited to dictionary literals. These operations hash their argument too:
| Code | Why it hashes |
|---|---|
d[[1, 2]] = 1 or d.get([1, 2]) | Dictionary keys are looked up by hash |
s.add([3]), set(list_of_lists) | Set members must be hashable |
[1] in {1, 2} | Membership in a set or dict hashes the left side |
A function decorated with functools.lru_cache called with a list | The cache key is built from the arguments |
Counter(list_of_lists), dict.fromkeys(list_of_lists) | Each item becomes a key |
The traceback shows the line; on Python 3.11 and later the carets point at the exact expression that was hashed.
Cached functions
functools.lru_cache requires hashable arguments. Convert lists to tuples at the call site, or add a thin wrapper that does it:
cat > cache.py <<'EOF'
from functools import lru_cache
@lru_cache
def total(items):
return sum(items)
try:
total([1, 2, 3])
except TypeError as e:
print("list:", e)
print("tuple:", total((1, 2, 3)))
EOF
python cache.pyOutput
list: unhashable type: 'list' tuple: 6
Prevent it
Choose immutable types for anything used as an identifier: tuples for composite keys such as (x, y) coordinates, frozensets for unordered groups, and strings or numbers for IDs. When data arrives as JSON, arrays become lists, so convert them before using them as keys.
FAQ
Why can a tuple be a dictionary key but a list cannot?
A dictionary finds keys by their hash, so a key must keep the same hash for its whole life. A list can change after it is stored, which would make the entry unreachable, so lists define no hash. Tuples are immutable and hash their items.
What about unhashable type: 'dict' or 'set'?
It is the same error for the other built-in mutable containers. Convert a set to a frozenset, and a dict to something immutable such as tuple(sorted(d.items())) when its values are hashable.
How do I remove duplicate lists from a list while keeping order?
Track what you have seen as tuples: seen = set(); keep only the rows whose tuple(row) is not in seen, adding it as you go. dict.fromkeys(map(tuple, rows)) also keeps the first occurrence in order.