How to Fix: TypeError: unhashable type: ‘dict’

3D illustration of a robot trying to unlock a safe using a soft sack instead of a metal key, representing the unhashable type dict error.

This TypeError unhashable dict is a direct cousin to unhashable type: ‘list’. It’s a core Python rule: You cannot use a mutable (changeable) object as a dictionary key or in a set.

  • “Hashable” (Immutable): str, int, tuple. These can be keys.
  • “Unhashable” (Mutable): list, dict, set. These cannot be keys.

⚡ Quick Fix: TypeError: unhashable type: ‘dict’ – Python Dictionary Key Immutability and frozenset Fix

You used a dictionary as a key inside another dictionary — mutable objects have no stable hash value, so Python rejects them as keys entirely.

user = {"id": 123, "name": "Alice"}

# Fix 1 — Use an immutable value from the dict as the key
settings = {user["id"]: "Dark Mode"}
print(settings[123])  # Output: Dark Mode

# Fix 2 — Convert dict contents to a frozenset for a hashable key
frozen_key = frozenset(user.items())
settings = {frozen_key: "Dark Mode"}  # Works

This tells you exactly where your boundary is — now read through the root causes below to find which one broke your code and fix it permanently.

The Cause

You are trying to use an entire dictionary as a key for another dictionary. Problem Code:

# A dictionary representing a user
user = {"id": 123, "name": "Alice"}

# A dictionary to store user settings
# We try to use the 'user' dict as the key
settings = {
    user: "Dark Mode"
}
# CRASH! TypeError: unhashable type: 'dict'

Python throws this error because if you later changed the user dictionary (e.g., user["age"] = 30), Python would lose track of where it stored the “Dark Mode” value.

The Fixes

Fix 1: Use an Immutable Piece of the Dict as the Key

The most common fix is to use a unique, immutable value from the dictionary as the key. The user’s ID is perfect for this.

user = {"id": 123, "name": "Alice"}
user_id = user["id"] # user_id is an 'int' (hashable)

settings = {
    user_id: "Dark Mode" # Correct!
}
print(settings[123])
# Output: Dark Mode

Fix 2: Convert the Dict to a frozenset (Advanced)

If you must use the dictionary’s contents as a key, you can convert its items into a frozenset, which is hashable.

user = {"id": 123, "name": "Alice"}

# .items() gives [('id', 123), ('name', 'Alice')]
frozen_key = frozenset(user.items())

settings = {
    frozen_key: "Dark Mode" # Works, but is less common
}

What This Error Exposes About Python’s Hashing Contract

TypeError: unhashable type: 'dict' is Python enforcing the fundamental contract of hash-based data structures. Dictionaries and sets store keys by computing a hash — a fixed integer derived from the key’s contents. That hash must remain stable for the lifetime of the key, because Python uses it to locate stored values later. A mutable object like a dictionary can change after insertion, which would change its hash and make the stored value permanently unreachable. Python blocks the insertion entirely rather than allow silent data loss.

The immutability rule maps directly to Python’s type hierarchy. Strings, integers, and tuples are immutable — their contents cannot change after creation, so their hash values are stable forever. Lists, dictionaries, and sets are mutable — their contents can change at any time, so Python never assigns them a hash value at all. Calling hash() on any mutable type raises TypeError immediately, and that same check runs internally every time you use an object as a dictionary key or add it to a set.

The frozenset fix works because frozenset is the immutable counterpart to set — its contents are locked at creation and its hash is computed once and cached. frozenset(user.items()) converts the dictionary’s key-value pairs into an immutable set of tuples, which is fully hashable. That pattern is correct for cases where the entire dictionary’s contents form the logical identity of the key — such as caching function results keyed by parameter combinations. For most real-world cases, extracting a unique immutable identifier like an ID or UUID is cleaner, faster, and more readable than a frozenset conversion.

Similar Posts

Leave a Reply