Skip to content

What doctor --fix fixes 1.4 ​

pypilot doctor --fix (the Fix environment button in the editors) fixes what is wrong and nothing else. Before 1.4.0 it rebuilt the environment for every problem. Now each finding gets its own fix.

  • A healthy project is left alone.
  • The Python moves only when a dependency forces it, and the output says which one.
  • An existing .python-version pin wins unless a dependency forces a change. The Python a fix picks is written to .python-version, so a later uv sync keeps it.
  • Every file PyPilot edits is named in the output.
  • An edit that leaves the project unresolvable is rolled back.
  • Conflicts are resolved before anything changes, and each proposed edit is checked with uv first.

Run pypilot doctor --fix --dry-run to see exactly what the real run would do. See Dry runs.

Problems and fixes ​

The last column is the fix.kind value in the JSON output.

ProblemWhat PyPilot doesFix kind
Damaged venv (broken interpreter, missing pyvenv.cfg, system site-packages leaking in)Repairs the venv on the Python it already hadrepair_environment
VIRTUAL_ENV pointing at another projectSays so; the shell setting is yours to changemanual
Venv in venv/ or env/Fixes it in placerepair_environment
Package missing or drifted from the lockuv sync --lockedsync_environment
Package half-installedReinstalls only that packagereinstall_packages
Stale uv.lockuv lockrelock
requires-python or .python-version that the venv breaksRebuilds on a Python that fits, only when neededrepair_environment
A dependency needs a newer Python than requires-python allowsRaises requires-python and names the dependencyraise_requires_python
Unsatisfiable pinsOffers a relaxed pin, checked with uv, then re-resolvesedit_requirement
Typo in a package name"Did you mean", then edits the requirementedit_requirement
Version that does not existNames the nearest releases and edits the requirementedit_requirement
No build for this OS (for example uvloop on Windows)Adds an environment markeredit_requirement
Compiled package that breaks under numpy 2 (pandas before 2.2.2)Reports it and edits the requirement, then re-resolvesedit_requirement
Uncapped dependency that later removed an API (markupsafe/jinja2, werkzeug/flask, itsdangerous/flask, urllib3/requests-toolbelt, sqlalchemy/flask-sqlalchemy, importlib-metadata/flake8, setuptools 82 and pkg_resources)Reports it and edits the requirement, then re-resolvesedit_requirement
Packages that shadow each other or the standard library (jwt and PyJWT, enum34, typing)Replaces the package with the right distributionreplace_dist
Yanked pinEdits the requirementedit_requirement
Stdlib module removed in a newer Python (distutils, imp, the 3.13 removals)Names the Python that removed it and adds the replacement package where there is one (setuptools for distutils). A dead package with no replacement (nose on 3.12) gets a Python that still has the module, when the project allows itadd_requirements, edit_requirement or recreate_with_python
Removed API used in your own code (np.float, collections.Mapping, asyncio.coroutine, pydantic.BaseSettings, SQLAlchemy 2 engine.execute, pandas 2 DataFrame.append)Reports file, line and the code to write instead, and keeps reporting it until the code changes. Adds a package when the replacement needs one (pydantic-settings)manual, or add_requirements
Import with no declared package (yaml, sklearn)Adds the right distribution (PyYAML, scikit-learn)add_requirements
Obvious mistake in a requirements.txt line (requests=2.31)Fixes the line. Reports the rest by line numberedit_requirement
pixi project, wrong Python or broken prefixApplies pixi add python=X.Y, repairs the prefixsee the output
conda environment.ymlMoves to pixi and keeps its Pythonmigrate_conda_to_pixi
Poetry projectReads ^/~ constraints and groups, installs with Poetrypoetry_install

pypilot fix requirements applies only doctor's requirement edits, without touching the environment. requirements.txt no longer overwrites pyproject.toml pins. A disagreement between them is reported.

Known breakages ​

Some breakages do not show in package metadata. They live in the known_breakages.json data table, which installed engines refresh from main every week. A new row reaches users without a release.

What it will not do ​

  • It never edits your source code. Removed APIs are reported with the replacement, and you make the change.
  • It never touches your global uv Python pin.
  • It does not run when requires-python is impossible, such as >=3.16 or >=3.10,<=3.9. That is an error, and nothing is built.

How well it works ​

PyPilot was run on 54 deliberately broken environments. 45 got the right targeted fix, none got a wrong one and none were missed. Before these changes, the same set had 13 right, 9 wrong and 21 missed.

Engine: AGPL-3.0-or-later. Zed and VS Code extensions: Apache-2.0. pypilot-cli: AGPL-3.0-or-later.