TypeError: unhashable type: 'list'
1 · The lesson
readWhat 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 coversdict and set, with the same message and a different type name.
When you see it
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'.
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:
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:
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.
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:
skills_seen = {frozenset(["python", "sql"])}
print(frozenset(["sql", "python"]) in skills_seen) # TrueA 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(...)ordf.drop_duplicates()on a column whose cells hold lists. - Building a graph as
edges = {[a, b]: weight}instead of{(a, b): weight}.
Related errors
- TypeError: list indices must be integers or slices, not str — using a list where a dict was expected, the other way round.
- KeyError: 'X' — the key was hashable, but it isn't in the dictionary.
- RuntimeError: dictionary changed size during iteration — another rule that exists so a dict can keep track of its keys.
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.inShort exercises that run in your browser and tell you what your code actually did, not just whether a test passed.