{"record":{"id":"1a0adb70872ecf69","repo":"pypa/pip","slug":"uninstall-distutils-installed-package","errorCode":"uninstall-distutils-installed-package","errorMessage":"Cannot uninstall {distribution}","messagePattern":"Cannot uninstall (.+?)","errorType":"exception","errorClass":"LegacyDistutilsInstall","httpStatus":null,"severity":"error","filePath":"src/pip/_internal/req/req_uninstall.py","lineNumber":510,"sourceCode":"                try:\n                    namespace_packages = dist.read_text(\"namespace_packages.txt\")\n                except FileNotFoundError:\n                    namespaces = []\n                else:\n                    namespaces = namespace_packages.splitlines(keepends=False)\n                for top_level_pkg in [\n                    p\n                    for p in dist.read_text(\"top_level.txt\").splitlines()\n                    if p and p not in namespaces\n                ]:\n                    path = os.path.join(dist_location, top_level_pkg)\n                    paths_to_remove.add(path)\n                    paths_to_remove.add(f\"{path}.py\")\n                    paths_to_remove.add(f\"{path}.pyc\")\n                    paths_to_remove.add(f\"{path}.pyo\")\n\n        elif dist.installed_by_distutils:\n            raise LegacyDistutilsInstall(distribution=dist)\n\n        elif dist.installed_as_egg:\n            # package installed by easy_install\n            # We cannot match on dist.egg_name because it can slightly vary\n            # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg\n            # XXX We use normalized_dist_location because dist_location my contain\n            # a trailing / if the distribution is a zipped egg\n            # (which is not a directory).\n            paths_to_remove.add(normalized_dist_location)\n            easy_install_egg = os.path.split(normalized_dist_location)[1]\n            easy_install_pth = os.path.join(\n                os.path.dirname(normalized_dist_location),\n                \"easy-install.pth\",\n            )\n            paths_to_remove.add_pth(easy_install_pth, \"./\" + easy_install_egg)\n\n        elif dist.installed_with_dist_info:\n            for path in uninstallation_paths(dist):","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/req/req_uninstall.py#L492-L528","documentation":"In the uninstall path (req_uninstall.py:510), when a distribution was installed by plain distutils (dist.installed_by_distutils), pip raises LegacyDistutilsInstall (code uninstall-distutils-installed-package). distutils installs don't write a usable RECORD, so pip cannot accurately determine the file set and refuses a partial uninstall.","triggerScenarios":"Uninstalling a package that was installed via `python setup.py install` using the stdlib distutils (no wheel, no RECORD).","commonSituations":"Legacy `python setup.py install` workflows; old system-Python packages; packages from before pip/wheel became standard.","solutions":["Reinstall the package properly via pip (pip install --force-reinstall <pkg>) so it gets a RECORD, then uninstall.","Manually remove the installed files and .egg-info directory.","Start fresh in a new virtualenv to avoid the legacy install entirely."],"exampleFix":"# before\npython setup.py install   # later: pip uninstall fails\n# after\npip install .  # then pip uninstall works","handlingStrategy":"validation","validationCode":"# Detect distutils-installed packages before uninstall.\nimport pathlib, sys, importlib.metadata as md\nfor dist in md.distributions():\n    base = pathlib.Path(dist.locate_file(\"\"))\n    egg_info = list(base.parent.glob(\"*.egg-info\"))\n    installer = (pathlib.Path(dist._path).parent / \"INSTALLER\").read_text().strip() if hasattr(dist, '_path') else \"\"\n    if egg_info and installer not in (\"pip\",):\n        print(f\"Possibly distutils-installed: {dist.metadata['Name']}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use `python setup.py install`; always use `pip install`.","Start new projects on a fresh venv with pip-only installs.","If you inherit an env, reinstall legacy packages via pip before uninstalling."],"tags":["uninstall","distutils","legacy"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}