RuntimeError: dictionary changed size during iteration

Python · updated 2026-11-03

Raised on the next step of a loop over a dict (or its keys, values or items) after the dict gained or lost a key inside the loop. Sets raise the same error with "Set changed size during iteration".

Traceback (most recent call last):
  File "/app/cache.py", line 21, in evict_expired
    for key, entry in self._items.items():
RuntimeError: dictionary changed size during iteration

Quick fix

Iterate over a snapshot when you need to delete or add keys: for key, entry in list(d.items()). Or build a new dict with a comprehension and replace the old one. If another thread changes the dict, protect it with a lock.

  1. Find the loop on the failing line and the line inside it that adds or deletes keys.
  2. Loop over list(d.items()) (or list(d)) so the loop has its own copy.
  3. For filtering, build a new dict: d = {k: v for k, v in d.items() if keep(v)}.
  4. If threads share the dict, guard reads and writes with a threading.Lock.
python
# Before: deleting while iterating the same dict
# for key, entry in cache.items():
#     if entry.expired:
#         del cache[key]

for key, entry in list(cache.items()):   # iterate a snapshot
    if entry.expired:
        del cache[key]

# Or replace it in one step
cache = {k: e for k, e in cache.items() if not e.expired}

Why it happens

Deleting keys inside the loop

Removing expired or invalid entries with del or pop while looping over the same dict is the most common case.

Adding keys inside the loop

Setting d[new_key] while iterating, including through a defaultdict whose missing-key lookup creates the key, changes the size just the same.

Another thread changing the dict

A background thread or a callback that writes to a shared dict while the main thread loops over it raises this error at random, which makes it look flaky.

Iterating over module or object state that changes

Looping over sys.modules, vars(obj) or globals() while code imports a module or sets an attribute can change those dicts under the loop.

Other fixes

  • Changing values for existing keys is fine: only adding or removing keys breaks the loop.
  • Collect keys to delete in a list during the loop and delete them after it.

Same error, other wording

  • RuntimeError: Set changed size during iteration
  • RuntimeError: OrderedDict mutated during iteration
  • RuntimeError: dictionary keys changed during iteration

Let your coding agent catch the next one

Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:

> Find the 'dictionary changed size during iteration' errors in production, show me each loop and what changes the dict inside it, and fix it by iterating a snapshot or rebuilding the dict.

Plans from $29/moSee what your agent readsSee the setupCancel any time from the billing portal

Related errors

References: Python docs: dictionary view objects, Python docs: built-in exceptions (RuntimeError)