Skip to content
Latchkey

Python "RuntimeError: dictionary changed size during iteration" in CI

Python detected that a dict (or set) gained or lost entries while a loop was iterating over it. Mutating the container mid-iteration invalidates the iterator, so the interpreter raises rather than skip or repeat keys.

What this error means

A loop fails with "RuntimeError: dictionary changed size during iteration". It can be intermittent if the mutation depends on data order.

python
Traceback (most recent call last):
  File "app/cache.py", line 18, in evict
    for key in cache:
RuntimeError: dictionary changed size during iteration

Diagnose it: is it the build backend or a missing system library?

Python packaging failures in CI split into build-backend configuration problems and missing system headers. The traceback usually points at the backend even when the real cause is an absent -dev package.

Terminal
python -m pip install --upgrade pip build
python -m build --wheel 2>&1 | tail -40

# a compiler error naming a .h file is a system dependency, not a Python one
#   e.g. "Python.h: No such file" -> python3-dev
#        "openssl/ssl.h"          -> libssl-dev

Common causes

Adding or deleting keys inside the loop

Calling del d[k] or d[new] = ... while iterating for k in d: changes the size and breaks the live iterator.

A helper mutates the same dict during iteration

A function called inside the loop writes to the dict being iterated, indirectly changing its size.

How to fix it

Iterate over a snapshot

Loop over a copy of the keys so mutating the original is safe.

app/cache.py
for key in list(cache.keys()):
    if expired(cache[key]):
        del cache[key]

Build a new dict instead of mutating in place

Compute the result as a comprehension and reassign, avoiding mid-loop mutation entirely.

app/cache.py
cache = {k: v for k, v in cache.items() if not expired(v)}

How to prevent it

  • Never add or remove keys while iterating a dict or set directly.
  • Iterate over list(d) or list(d.items()) when you must mutate.
  • Prefer rebuilding the container with a comprehension.

Frequently asked questions

What causes Python "RuntimeError: dictionary changed size during iteration" in CI?
There are 2 common causes: adding or deleting keys inside the loop and a helper mutates the same dict during iteration. Calling del d[k] or d[new] = ...
How do I fix Python "RuntimeError: dictionary changed size during iteration" in CI?
There are 2 fixes depending on which cause you have: iterate over a snapshot and build a new dict instead of mutating in place. Work through them in order, since the first is the most common.
What does Python "RuntimeError: dictionary changed size during iteration" in CI actually mean?
A loop fails with "RuntimeError: dictionary changed size during iteration".
How do I stop Python "RuntimeError: dictionary changed size during iteration" in CI happening again?
Never add or remove keys while iterating a dict or set directly. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card