pypa/pip · error · UninstallMissingRecord

uninstall-no-record-file

uninstall-no-record-file

Error message

Cannot uninstall {distribution}

What it means

uninstallation_paths (req_uninstall.py:77) raises UninstallMissingRecord (DiagnosticPipError, code uninstall-no-record-file) when dist.iter_declared_entries() returns None — meaning the package's .dist-info/RECORD is absent. Without RECORD pip cannot enumerate which files to remove, so it refuses rather than do a partial uninstall.

Solutions

  1. Force a clean reinstall then uninstall: pip install --ignore-installed --no-deps <pkg>==<ver> then pip uninstall <pkg>.
  2. Use the original installer (conda remove, apt purge) to remove the package.
  3. Manually delete the package files and its .dist-info directory.

Example fix

# before
pip uninstall corruptedpkg  # fails: no RECORD
# after
pip install --ignore-installed --no-deps corruptedpkg==1.0 && pip uninstall corruptedpkg
Defensive patterns

Strategy: validation

Validate before calling

# Before pip uninstall, check whether a RECORD file exists.
import importlib.metadata as md, pathlib, sys
target = sys.argv[2]  # e.g. pkg name
try:
    dist = md.distribution(target)
    record = pathlib.Path(dist._path) / "RECORD"  # type: ignore
    if not record.exists():
        print(f"WARNING: {target} has no RECORD; reinstall first:",
              f"pip install --ignore-installed --no-deps {target}=={dist.version}")
except md.PackageNotFoundError:
    pass

Prevention

When it happens

Trigger: Running pip uninstall on a package whose .dist-info lacks a RECORD file — installed by a non-pip tool (conda, easy_install, hand-copy, system package manager).

Common situations: Conda-installed packages in a shared env; packages copied manually; legacy easy_install eggs; partial/corrupted installs.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/34e7d11bea8bf4c7. Report an issue: GitHub.

Appendix: source

Thrown at src/pip/_internal/req/req_uninstall.py:77

    """
    Yield all the uninstallation paths for dist based on RECORD-without-.py[co]

    Yield paths to all the files in RECORD. For each .py file in RECORD, add
    the .pyc and .pyo in the same directory.

    UninstallPathSet.add() takes care of the __pycache__ .py[co].

    If RECORD is not found, raises an error,
    with possible information from the INSTALLER file.

    https://packaging.python.org/specifications/recording-installed-packages/
    """
    location = dist.location
    assert location is not None, "not installed"

    entries = dist.iter_declared_entries()
    if entries is None:
        raise UninstallMissingRecord(distribution=dist)

    for entry in entries:
        path = os.path.join(location, entry)
        yield path
        if path.endswith(".py"):
            dn, fn = os.path.split(path)
            base = fn[:-3]
            path = os.path.join(dn, base + ".pyc")
            yield path
            path = os.path.join(dn, base + ".pyo")
            yield path


def compact(paths: Iterable[str]) -> set[str]:
    """Compact a path set to contain the minimal number of paths
    necessary to contain all paths in the set. If /a/path/ and
    /a/path/to/a/file.txt are both in the set, leave only the
    shorter path."""

View on GitHub (pinned to f399c37189)