Skip to content

Multi-root pytest discovery loop spawns thousands of processes and freezes macOS #1984

Open

Description

Searched existing issues on 2026-11-04 and found no duplicate. Related:
microsoft/vscode-python#25718, microsoft/vscode-python#24683 (closed).


Environment data

  • Python Environments extension version: 1.40.0
  • Python extension (ms-python.python) version: 2026.10.0 (Pylance 2026.4.1)
  • VS Code version (Help → About): 1.144.1 (storms 1–4), 1.145.0 (storm 5)
  • OS and version: macOS 27.2 (26B123), Apple M4 Max, 48 GB
  • Python version (& distribution if applicable, e.g. Anaconda): 3.14.7 (uv-managed)
  • Environment manager in use (venv / conda / pyenv / poetry / pipenv / system / uv / other): uv 0.13.6 (.venv per project)
  • Shell (bash / zsh / fish / pwsh / cmd / other): zsh
  • Remote / container scenario (none / WSL / SSH Remote / Dev Container / Codespaces): none
  • Workspace type (single folder / multi-root / mono-repo): multi-root (.code-workspace with 6 folders, each a uv project)
  • Is this a regression? If yes, last known working extension version: Probably. The extension versions
    were unchanged from Oct 15 and ran without issue until VS Code updated to 1.144.1 on Nov 1. The first
    storm came on Nov 2. The last known working combination is Python Environments 1.40.0 with the VS Code
    release before 1.144.1.

Repro Steps

  1. Open a .code-workspace with 6 folders (proj1–proj6). Each is a uv project with its own .venv;
    some have a tests/ directory and some don't. Workspace settings:

    "python.defaultInterpreterPath": "${workspaceFolder:proj1}/.venv/bin/python",
    "python.testing.pytestArgs": ["tests"],
    "python.testing.pytestEnabled": true,
    "python.testing.unittestEnabled": false,
    "files.watcherExclude": { "**/.venv/**": true }
  2. Let initial test discovery finish (normal: about 6–12 discovery subprocesses).

  3. Keep working in the window for hours (editing, running uv commands, opening files). I have no
    deterministic trigger yet.

  4. Watch ps or the Python output channel. At some point, discovery rounds start and keep repeating.

What I know about the trigger:

  • All 5 storms came 0–10 s after a uv command, but uv alone isn't sufficient. A harness that ran
    uv sync, uv run, venv touches, file saves and window reloads in random order (4 cycles with the
    extension enabled, then 10 cycles on 1.144.1) never caused one. Fresh windows never stormed.
  • In 3 of 5 storms, Starting Pylance language server was logged 2–3 s before the first wave.
  • Storm 5 reproduced under the harness 2 h 48 min into a session on 1.145.0. It followed
    uv sync --reinstall-package <pkg> in one project, then the YAML, Markdown and Python language
    features activating at the same moment, as if several changed files had been opened (for example
    in Source Control diffs). Pylance restarted 2 s before the first wave, which then produced 565 spawns
    in 7 s.
  • Working theory: a long-session race between environment refresh, a Pylance restart and an
    in-progress discovery.

Expected behavior

At most one test discovery per project after an environment change. A new round should cancel or wait
for one that is already running. Each project should use its own interpreter.

Actual behavior

  • The [test-by-project] discovery starts a new round for all 6 folders about every 0.5 s, without
    waiting for earlier rounds to finish and with no further environment change logged.
  • Every round runs proj1/.venv/bin/python -m pytest -p vscode_pytest --collect-only tests --rootdir=<folder>
    for each folder, so all projects use proj1's interpreter.
  • In about 2 minutes, about 1,900 subprocesses start and only about 20% complete.
  • Memory runs out and macOS hard-freezes: WindowServer stops responding.
  • Killing the pytest children does not stop it: the extension host starts new ones within seconds
    (a watchdog killed 4,825 processes in storm 5). Only killing the extension host stopped it.
  • This happened 5 times in 3 days. 3 needed a forced restart, 1 was stopped by hand (storm 5) and 1
    ended in a kernel panic:
    userspace watchdog timeout: no successful checkins from WindowServer. The panic stackshot showed
    1,368 python3.14 processes, 1,367 orphaned to launchd.

Discovery subprocesses started per minute, from the Python output channel log (normal is 6–12):

Storm Spawns per minute Outcome
Nov 2 18:03–18:04 1,368, then 132 Freeze 18:08
Nov 3 13:49–13:50 367, then 1,091 Freeze 13:52
Nov 3 15:42–15:43 1,241, then 338 Kernel panic 15:49
Nov 4 09:57–09:58 864, then 1,050 Freeze 10:00
Nov 4 17:38–17:48 (VS Code 1.145.0) 565 in the first 7 s, then repeated waves Extension host killed by hand, no freeze

Python output channel counts for Nov 4, 09:57–09:58:

  • Discovering projects for workspace: 1,920
  • Started pytest discovery subprocess: 1,914
  • Pytest discovery completed: about 400
  • ERROR: file or directory not found: tests: 134 (folders without tests/)
  • Environment change detected: 0, so the rounds restart with no logged trigger

A process snapshot 2 s into the storm showed 144 python processes, all children of the extension host
(Code Helper (Plugin)). Killing them did not help, because the extension host kept respawning them.

Workaround: disabling Python Environments (ms-python.vscode-python-envs) alone. With it disabled,
5 triggers produced 0 discovery spawns. It was re-enabled for testing, so there's no long-term
confirmation that it prevents storms.

Logs

Info-level logs, captured after the fact. Trace logs weren't enabled, because each repro freezes the
machine. Paths are anonymized.

Python Environments output channel, start of the storm:

2026-11-04 09:57:45.412 [error] [pet] WARN pet_telemetry: Inaccurate Python Environment Info for => (an unrelated venv outside the workspace)
2026-11-04 09:57:45.417 [info] Running in background: "~/Projects/proj1/.venv/bin/python3" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj1
2026-11-04 09:57:45.418 [info] Resolved Python Environment ~/Projects/proj1/.venv/bin/python
2026-11-04 09:57:45.420 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj3
2026-11-04 09:57:45.421 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj2
2026-11-04 09:57:45.421 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj5
2026-11-04 09:57:45.422 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj4
2026-11-04 09:57:45.423 [info] Resolved Python Environment ~/Projects/other-project/.venv/bin/python
2026-11-04 09:57:45.445 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj6
2026-11-04 09:57:45.455 [info] Resolved Python Environment ~/Projects/proj1/.venv/bin/python
2026-11-04 09:57:45.460 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj2
2026-11-04 09:57:45.461 [info] Running in background: "~/Projects/proj1/.venv/bin/python" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj3
2026-11-04 09:57:45.461 [info] Running in background: "~/Projects/proj1/.venv/bin/python3" -m pytest -p vscode_pytest --collect-only tests --rootdir=~/Projects/proj1
...

Resolved Python Environment was logged 325 times in this window.

Python output channel, start of the storm and one repeating round:

2026-11-04 09:57:43.168 [info] Active interpreter [~/Projects/proj6]:  ~/Projects/proj1/.venv/bin/python
2026-11-04 09:57:43.168 [info] Starting Pylance language server.
2026-11-04 09:57:45.350 [info] > conda info --json
2026-11-04 09:57:45.359 [info] > pyenv which python
2026-11-04 09:57:45.387 [info] [test-by-project] Cleaned up 1 test items for workspace: ~/Projects/proj1
...
2026-11-04 09:57:48.577 [info] [test-by-project] Found 6 total Python projects from API
2026-11-04 09:57:48.577 [info] [test-by-project] Filtered to 1 projects in workspace
2026-11-04 09:57:48.629 [info] [test-by-project] Registered 1 project(s) for ~/Projects/proj6
2026-11-04 09:57:48.640 [info] [test-by-project] Starting discovery for 1 project(s) in workspace
2026-11-04 09:57:48.640 [info] [test-by-project] Discovering tests for project: proj1 (Python 3.14)
2026-11-04 09:57:48.668 [info] [test-by-project] Cleaned up 0 test items for workspace: ~/Projects/proj1
2026-11-04 09:57:48.668 [info] [test-by-project] Discovering projects for workspace: ~/Projects/proj1

Also seen intermittently:

[error] Invalid version for ~/Projects/proj1/.venv/bin/python: {"name":"proj1 (3.14.x)", ...}

Additional context

  • Timeline: macOS 27.2 was installed Oct 29. VS Code sessions on Oct 29–30 and the morning of Nov 2 ran
    [test-by-project] discovery normally (at most 12 spawns per minute). VS Code updated to 1.144.1 on
    Nov 1, and the first storm came Nov 2 17:39. Every storm afterwards came within seconds of a uv command.
    Storm 5 shows the problem also happens on 1.145.0 with the same extension versions.
  • A pet warning (Inaccurate Python Environment Info) for an unrelated venv appeared at the start of
    storms 4 and 5.
  • The OS turns the storm into a hard freeze through memory exhaustion, but the processes all come from
    the extension host.
  • Related: pytest discovery does not use specified environment vscode-python#25718 (pytest discovery uses the wrong environment in a monorepo,
    suspected race between the two extensions), and Pytest Discovery Loop Bug vscode-python#24683 (macOS discovery loop,
    closed). This storm grows without bound.
  • Anonymized logs from all 5 storms are available on request (about 31 MB). The Python Environments
    and Python output channel logs are Info level, because Trace would need another freeze.

Activity

  1. changed the title [-]Python Environments: multi-root pytest discovery loop spawns thousands of processes and freezes macOS[/-] [+]Multi-root pytest discovery loop spawns thousands of processes and freezes macOS[/+] on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions