How to Resolve "pip install Error: legacy-install-failure"
Quick answer
Installing a package fails with a generic "legacy-install-failure" summary, which is pip's way of saying a package's older-style build process crashed β but...
Installing a package fails with a generic "legacy-install-failure" summary, which is pip's way of saying a package's older-style build process crashed β but that summary line hides the actual, specific error you need to see. The real cause is almost always buried a bit higher up in the same output.
The Problem
The install fails with a message that doesn't explain what actually went wrong:
$ pip install psycopg2
...
error: legacy-install-failure
Γ Encountered error while trying to install package.
β°β> psycopg2
note: This is an issue with the package mentioned above, not pip.
The real cause is almost always visible earlier in the same output, easy to miss if you only read the last few lines:
Error: pg_config executable not found.
pg_config is required to build psycopg2 from source.
Why It Happens
"legacy-install-failure" is a generic wrapper pip shows when a package's build step (using the older setup.py-based build process rather than a modern wheel) fails for any reason β pip doesn't try to interpret the underlying error, it just reports that the build process exited with a failure. The actual cause varies widely, but the most common patterns are:
- Missing system-level build dependencies β many Python packages that wrap C libraries (psycopg2 for PostgreSQL, mysqlclient for MySQL, lxml for XML parsing) need corresponding system libraries and header files installed before they can compile.
- Missing a C compiler entirely β a minimal server or container image often lacks
gccor build tools altogether. - An outdated
pip,setuptools, orwheelthat doesn't correctly handle a package's modern build configuration. - Python version incompatibility β the package (or the specific version you requested) doesn't have a pre-built wheel for your Python version and platform, forcing a from-source build that then fails for one of the above reasons.
The Fix
Always scroll up past the "legacy-install-failure" summary to find the actual underlying error β it's there, just further up in a typically long, noisy build log:
pip install psycopg2 2>&1 | tee install.log
less install.log
For the common "pg_config not found" case shown above, install the system PostgreSQL development package first:
# Debian/Ubuntu
sudo apt install libpq-dev python3-dev
# RHEL/CentOS
sudo yum install postgresql-devel python3-devel
# macOS
brew install postgresql
Retry the install:
pip install psycopg2
For many packages that require compiling C extensions, using the pre-compiled binary variant sidesteps the whole build process entirely β psycopg2-binary, for example, ships a pre-built wheel and doesn't need pg_config or a compiler at all:
pip install psycopg2-binary
Note that binary variants are convenient for development but generally discouraged for production deployments by their own maintainers, since they bundle their own copies of underlying C libraries that can drift out of sync with your system's versions β for production, installing the proper system dependencies and building from source (or using your OS package manager's Python bindings) is usually the more correct long-term choice.
If the failure isn't about a specific system library, update your core build tooling, which resolves a surprising number of these failures on its own:
pip install --upgrade pip setuptools wheel
Ensure a C compiler is actually available on the system:
# Debian/Ubuntu
sudo apt install build-essential
# RHEL/CentOS
sudo yum groupinstall "Development Tools"
Still Not Working?
If the underlying error mentions a specific missing header file (something like fatal error: Python.h: No such file or directory), that specifically means the Python development headers aren't installed β a common gap on minimal server images and Docker base images that include Python but not its development package:
sudo apt install python3-dev
If you're building inside a Docker image and want to avoid carrying the full build toolchain into your final production image, use a multi-stage build β install build dependencies and compile in an intermediate stage, then copy only the resulting installed packages into a slim final image, keeping the deployed image smaller and free of compiler toolchains it doesn't need at runtime.