pypa/pip · critical · RuntimeError

Python 3.8 or later is required

Error message

Python 3.8 or later is required

What it means

pkg_resources is guarded at import time: if the running interpreter is older than Python 3.8, it raises RuntimeError immediately. pkg_resources is vendored inside pip and itself deprecated, but this hard floor exists so an unsupported interpreter fails fast rather than producing subtle SyntaxError or behavioral bugs. The check is at module top level, so merely importing pkg_resources (or any module that imports it) on Python 3.7 or earlier triggers it.

Source

Thrown at src/pip/_vendor/pkg_resources/__init__.py:28

to have their path parts separated with ``/``, *not* whatever the local
path separator is.  Do not use os.path operations to manipulate resource
names being passed into the API.

The package resource API is designed to work with normal filesystem packages,
.egg files, and unpacked .egg files.  It can also work in a limited way with
.zip files and with custom PEP 302 loaders that support the ``get_data()``
method.

This module is deprecated. Users are directed to :mod:`importlib.resources`,
:mod:`importlib.metadata` and :pypi:`packaging` instead.
"""

from __future__ import annotations

import sys

if sys.version_info < (3, 8):  # noqa: UP036 # Check for unsupported versions
    raise RuntimeError("Python 3.8 or later is required")

import os
import io
import time
import re
import types
from typing import (
    Any,
    Literal,
    Dict,
    Iterator,
    Mapping,
    MutableSequence,
    NamedTuple,
    NoReturn,
    Tuple,
    Union,
    TYPE_CHECKING,

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Upgrade the interpreter to Python 3.8+ (3.7 reached end-of-life June 2023); recreate any virtualenvs from a supported interpreter.
  2. If stuck on an old Python, downgrade setuptools/pip to a version that still supported it, though this is not recommended long-term.
  3. Migrate away from pkg_resources (it is deprecated) to importlib.resources / importlib.metadata, which have their own version floors but are the supported path forward.

Example fix

// before
python3.7 -c "import pkg_resources"  # RuntimeError: Python 3.8 or later is required

// after
python3.11 -c "import pkg_resources"  # OK
Defensive patterns

Strategy: validation

Validate before calling

import sys
if sys.version_info < (3, 8):
    raise SystemExit('Python 3.8+ required; got %s' % '.'.join(map(str, sys.version_info[:3])))

# safe to import only after the check
import pkg_resources

Type guard

# interpreter-level, not type-level; guard with a version check
import sys
CAN_IMPORT_PKG_RESOURCES = sys.version_info >= (3, 8)

Try / catch

# ImportError/RuntimeError at import time cannot be usefully caught at the
# same import site; guard before importing:
# if sys.version_info >= (3, 8): import pkg_resources

Prevention

When it happens

Trigger: Executing `import pkg_resources` (directly or transitively via pip, setuptools, or any dependency) on CPython/PyPy 3.7 or older. The guard is `if sys.version_info < (3, 8): raise RuntimeError(...)`.

Common situations: System Python still on 3.6/3.7 (older distros), a virtualenv built from an old interpreter, CI matrix pinning an EOL Python, or a Docker base image with a legacy Python. Since pkg_resources is widely imported transitively, the error surfaces even when the user never names the module.

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/9dee09ca8339d240.json. Report an issue: GitHub.