PythonMastery
reference 4 min read · lesson 45 of 45 in Errors

TypeError: unhashable type: 'list'

1 · The lesson

read

What this error means

You tried to use a list as a dictionary key or as a member of a set. Both are built on hashing: Python turns the key into a number once and uses that number to find it again later. A list can change after you've stored it — append one item and its hash would change, and the dictionary would lose track of it. So Python refuses to hash lists at all. The same rule covers dict and set, with the same message and a different type name.

When you see it

text
Traceback (most recent call last):
  File "dedupe.py", line 5, in <module>
    seen.add(row)
TypeError: unhashable type: 'list'

Why it happens

Something mutable ended up where Python needs something fixed:

1. A set of lists. Deduplicating rows with set(rows) or seen.add(row), when each row is a list — which is exactly what csv.reader gives you.
2. A list as a dict key. Counting or grouping by a pair of values stored as [city, year].
3. A list hiding inside a tuple. (1, [2, 3]) is a tuple, but it's only hashable if everything inside it is.
4. The dict version. set_of_records.add({"id": 7}) fails the same way, with unhashable type: 'dict'.

python
rows = [["Oslo", 2024], ["Lima", 2024], ["Oslo", 2024]]
unique = set(rows)       # TypeError: unhashable type: 'list'

How to fix it

Turn the list into a tuple. A tuple can't change, so it can be hashed — and for a row of values it's the more honest type anyway:

python
rows = [["Oslo", 2024], ["Lima", 2024], ["Oslo", 2024]]
unique = {tuple(row) for row in rows}
print(unique)            # {('Oslo', 2024), ('Lima', 2024)}

Need to keep the original order while deduplicating? A set won't do that; a dictionary keyed by tuples will:

python
unique_rows = list(dict.fromkeys(tuple(row) for row in rows))
# [('Oslo', 2024), ('Lima', 2024)] — first appearance wins
+ setup added so this can run · defines rows
rows = ["alpha", "beta", "gamma"]

Counting by a combination of values? Key by a tuple.

python
from collections import Counter

visits = [["Oslo", 2024], ["Lima", 2024], ["Oslo", 2024]]
by_city_year = Counter(tuple(v) for v in visits)
print(by_city_year[("Oslo", 2024)])   # 2

Order of the items doesn't matter? Use frozenset — {"python", "sql"} and {"sql", "python"} become the same key:

python
skills_seen = {frozenset(["python", "sql"])}
print(frozenset(["sql", "python"]) in skills_seen)   # True

A dict as the key? Reach for its identifying field instead — records_by_id[record["id"]] — rather than trying to hash the whole thing.

When you'd actually see this in real code

  • Removing duplicate rows from a CSV with set(csv.reader(f)).
  • A cache decorator, functools.lru_cache, wrapped around a function you call with a list argument — the cache keys on the arguments.
  • pandas df.groupby(...) or df.drop_duplicates() on a column whose cells hold lists.
  • Building a graph as edges = {[a, b]: weight} instead of {(a, b): weight}.

See Also

  • All Python errors — the full index, by type and by when it happens.
  • Tuples — the immutable sequence, and why that makes it a good key.
  • Sets — what can go in one, and why.
  • Dictionaries — keys, hashing and lookups.

Practice this

on practicepython.in

Short exercises that run in your browser and tell you what your code actually did, not just whether a test passed.