Repository navigation
[3.15] Re-entrant calls to site.addsitedir() can fail (affecting uv run) #149504
Description
Bug report
Bug description:
I found a regression in Python 3.15’s site.py startup-file processing. A .pth file containing an import line that calls site.addsitedir() can re-enter process_startup_files() while _exec_imports() is iterating _pending_importexecs, causing recursive processing of the same .pth file and eventually a startup failure.
This was originally observed with uv run --with ..., because uv creates an ephemeral overlay .pth file like:
import site; site.addsitedir("/path/to/overlay/site-packages"); site.addsitedir("/usr/local/lib/python3.15/site-packages")But the issue can be reproduced without uv.
Environment
Python 3.15.0b1+ (heads/3.15:e81025e6d2e, May 7 2026, 10:29:46)
[Clang 15.0.0 (clang-1500.3.9.4)]
macOS arm64
Minimal Reproducer
mkdir -p /tmp/site-repro/root /tmp/site-repro/overlay
printf 'import site; site.addsitedir("/tmp/site-repro/overlay")\n' > /tmp/site-repro/root/reenter.pth
python3.15 -S -c 'import site; site.addsitedir("/tmp/site-repro/root"); print("done")'Expected Behavior
The .pth import line should execute once, add /tmp/site-repro/overlay as a site directory, and the command should print:
done
Actual Behavior
Python repeatedly processes the same .pth import line, then fails with errors like:
Error in import line from /tmp/site-repro/root/reenter.pth: import site; site.addsitedir("/tmp/site-repro/overlay")
...
RuntimeError: dictionary changed size during iteration
In startup contexts, such as uv run --with ..., this can become fatal during site initialization:
Fatal Python error: init_import_site: Failed to import the site module
Python runtime state: core initialized
Traceback (most recent call last):
File "<frozen site>", line 901, in <module>
File "<frozen site>", line 877, in main
File "<frozen site>", line 812, in venv
File "<frozen site>", line 598, in addsitepackages
File "<frozen site>", line 422, in addsitedir
File "<frozen site>", line 359, in process_startup_files
File "<frozen site>", line 303, in _exec_imports
RuntimeError: dictionary changed size during iteration
Likely Cause
In Lib/site.py, addsitedir() calls process_startup_files() unless defer_processing_start_files=True.
process_startup_files() calls _exec_imports(), which iterates directly over _pending_importexecs.items():
def _exec_imports():
for filename, imports in _pending_importexecs.items():
...
for line in imports:
exec(line)If one of those .pth import lines calls site.addsitedir(), then addsitedir() calls process_startup_files() again while the outer _exec_imports() is still iterating _pending_importexecs. That causes repeated execution and eventually RuntimeError: dictionary changed size during iteration.
Real-World Trigger
With uv 0.11.7:
uv run --python /Users/jelle/py/cpython/python.exe --with iniconfig python -c 'import iniconfig'fails before user code runs because uv’s ephemeral overlay .pth contains import site; site.addsitedir(...).
Plain uv run without --with works, so this is specifically triggered by .pth import lines that call site.addsitedir() during site startup.
CPython versions tested on:
3.15
Operating systems tested on:
macOS
Activity
JelleZijlstra commentedon May 7, 2026
cc @warsaw (pretty sure this is PEP-829)
brettcannon commentedon May 7, 2026
Might be a duplicate of #75723 which has a PR.
pythongh-149504: Fix reentrant site startup processing
Merge branch 'main' into zsol/pythongh-149504-reentrant-site-startup
warsaw commentedon May 11, 2026
I think that one's different, and I just landed a fix for it for 3.15, but it can't be backported to 3.13 and 3.14. I am going to take a look at the PR above later.
warsaw commentedon May 11, 2026
Confirmed, and yes the problem is that the
site.addsitedir()in the.pthfile hits the same global dictionaries that are being iterated over.I need to think about this further because you can't just copy the dictionaries before iterating over them.
process_startup_files()clears them after processing, and you don't want to be sure not to lose the re-entrantly added entries. Let me work up a test case, and then I have some ideas.Merge branch 'main' into pythongh-149504
Merge branch 'main' into pythongh-149504
Merge branch 'main' into pythongh-149504
Merge branch 'main' into pythongh-149504
pythongh-149504: Fix re-entrancy bug when .pth/.start file invokes si…
[3.15] gh-149504: Fix re-entrancy bug when .pth/.start file invokes s…