Pip Externally-Managed-Environment Error: The Safe Fix
Fix pip's externally-managed-environment error the safe way: use a venv or pipx, know when apt fits, and why --break-system-packages is a last resort.

If pip install stops with error: externally-managed-environment, your Python is marked as owned by the operating system's package manager, and pip refuses to touch it. The fix is to stop installing into the system Python. Create a virtual environment with python3 -m venv .venv and install into that, or use pipx if you're installing a command-line tool.
You don't need to remove the error, disable it, or bypass it. The marker is there so a stray pip install can't break OS tools written in Python. Below are the fixes in order from safest to riskiest, with a check after each one.
The externally-managed-environment error, exactly#
The error starts with this line:
error: externally-managed-environment
The text after it comes from the distribution, not from pip. A Debian-style message looks like the example in the Python packaging specification, roughly:
To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
If you wish to install a non-Debian packaged Python application,
it may be easiest to use pipx install xyz, which will manage a
virtual environment for you. Make sure you have pipx installed.
Your wording may differ. Raspberry Pi OS, Ubuntu and Kali are Debian derivatives, so you'll likely see something close to this. The exact message on your machine is whatever the distro put in its marker file. Read it, because it usually names the right commands for that system.
Why new Pythons block pip#
This is PEP 668. A distributor of Python can mark an interpreter as having its packages managed by something outside Python, such as apt. Python tools like pip then shouldn't add, upgrade, downgrade or remove packages in that interpreter's global sys.path unless you explicitly override it.
The mechanism is a file named EXTERNALLY-MANAGED in the interpreter's standard library directory. Before installing, pip checks two things:
- Are you running outside a virtual environment? (
sys.prefix == sys.base_prefix) - Does an
EXTERNALLY-MANAGEDfile exist in the stdlib directory?
If both are true, pip exits with the error. That's why the same pip install works fine inside a venv: the first condition is no longer true.
The mechanism is opt-in. A Python compiled from upstream sources isn't marked, and neither is a distro Python that hasn't added the file. That's why the error appears on some machines and not others, and why an old tutorial that worked for years suddenly fails after an OS upgrade.
The risk it guards against is real. The PEP notes reports of distro-installed packages being deleted after someone ran sudo pip install --upgrade pip, which left a /usr/bin/pip without Debian's protective patch. Mixing pip and the OS package manager in one directory ends badly eventually.
Fix 1: use a virtual environment#
This is the right answer for almost everyone, especially if you're working on a project and need libraries.
python3 -m venv .venv
source .venv/bin/activate
pip install requests
The venv module creates the directory, a pyvenv.cfg file, a bin subdirectory with the Python executable, and a lib/pythonX.Y/site-packages directory. pip is bootstrapped into it by default. On Windows the subdirectory is Scripts instead of bin.
You don't have to activate it. Calling the environment's own interpreter works too, which is handy in scripts and cron jobs:
.venv/bin/python -m pip install requests
.venv/bin/python my_script.py
Confirm it worked: with the venv active, this prints True.
python -c "import sys; print(sys.prefix != sys.base_prefix)"
The script below shows the same logic pip uses. It also parses a sample marker file with configparser, the way the spec describes. Run it in and out of a venv and compare.
import sys
import configparser
in_venv = sys.prefix != sys.base_prefix
print("inside a virtual environment:", in_venv)
sample = """
[externally-managed]
Error=Use a virtual environment: python3 -m venv path/to/venv
"""
cfg = configparser.ConfigParser(interpolation=None)
cfg.read_string(sample)
if cfg.has_section("externally-managed"):
print("marker message:", cfg["externally-managed"]["Error"])
print("pip would block a global install:", not in_venv and cfg.has_section("externally-managed"))
If python3 -m venv fails#
On Debian-style systems the venv module may not be fully installed. The Debian message above says to make sure python3-full is installed:
sudo apt install python3-full
That sudo installs through the OS package manager, which is exactly the right tool for system packages. Then retry the venv command.
Fix 2: use pipx for command-line tools#
If you want a Python application rather than a library for your own code, pipx is the better fit. It creates a separate virtual environment for each application automatically, so you never manage it by hand.
sudo apt install pipx
pipx install xyz
Replace xyz with the tool name. The Debian message recommends this path for non-Debian-packaged Python applications, and the PEP calls it a much better default for people who want Python software but aren't Python developers themselves. Install pipx from your distro's package manager if it offers one, as above, rather than with pip.
Confirm it worked: run the tool by name. If the command isn't found, check your shell's PATH; the pack doesn't cover pipx's PATH setup, so see its own documentation for that.
Fix 3: install the distro's own package#
If your distro already packages the library, that's often the cleanest option for system-wide use, particularly for scripts that run as system services. The error message itself suggests the pattern:
sudo apt install python3-xyz
Here xyz is the package you want. Names and versions come from the distro, so you may get an older release than PyPI has. If you need a specific version, go back to Fix 1.
Fix 4 (last resort): override with --break-system-packages#
Warning: This flag exists so you can override the protection, and the spec says it "should carry some connotation that its use is risky." It can overwrite or change packages that OS tools depend on, and recovering a broken system Python is much harder than recreating a venv. Use it only when none of the fixes above fit, and never with
sudounless you understand what gets written.
pip install --break-system-packages xyz
With this flag, pip installs into the global context anyway. On Debian and Fedora style layouts, the spec recommends keeping locally installed packages in /usr/local and distro packages in /usr, so a normal install shouldn't touch the distro's files. That split is a recommendation for distros, not a guarantee on every system, so check yours.
The PEP itself points out the irony of telling people to run pip install --user --break-system-packages pipx. If you're tempted to do that, install pipx through the OS package manager instead.
Removing or disabling the check#
People searching for how to remove, disable or bypass the error mostly want one of two things.
- Make the error go away for one command: that's
--break-system-packages, covered above. - Make it go away permanently: that means deleting or renaming the
EXTERNALLY-MANAGEDfile in your stdlib directory. The spec treats suppressing the marker as something distributors do in build chroots and container images, not something an end user does on a working desktop. I'd skip it on any machine where OS tools use the system Python.
To find where the marker lives on your machine without guessing:
python3 -c "import sysconfig; print(sysconfig.get_path('stdlib', sysconfig.get_default_scheme()))"
If an EXTERNALLY-MANAGED file sits in that directory, that's your marker. Debian's example location is /usr/lib/python3.9/EXTERNALLY-MANAGED for Python 3.9.
Containers, conda and other cases#
The PEP walks through several setups. The ones readers hit most:
| Setup | pip install blocked by default? |
|---|---|
| Self-compiled upstream Python | No, works as it always has |
Distro /usr/bin/python3 with a marker file |
Yes |
| Distro Python inside a venv | No |
Venv with --system-site-packages |
No, and pip still won't delete packages outside the venv |
| Distro Python in a Docker image | Yes, if the distro ships the marker |
| Conda environment | No, behavior stays as it was |
For containers, the PEP says builders of single-application base images may choose to leave the marker out so plain RUN pip install ... lines keep working. Even so, its authors still think a venv is a good idea in a container, because OS commands implemented in Python can break if you upgrade the distro-shipped packages with pip.
A single-application image is the one place where I'd consider the flag acceptable, since you can rebuild the container. A venv costs a few lines and removes the question.
Common mistakes#
- Using
sudo pip install. It doesn't solve the error and is how many systems end up broken. Use a venv, with nosudo. - Upgrading system pip with sudo. The PEP suspects this causes some reports of deleted distro packages, because it replaces Debian's patched pip.
- Expecting
--userto dodge the check. The PEP's analysis covers bothpip installas root andpip install --useron a marked distro Python, so both are affected. - Creating the venv, then forgetting to activate it. Run
which piporwhich python. If it points to/usr/bin, you're still on the system interpreter. - Committing the venv to Git. The venv docs describe it as disposable and not meant to be checked in. Keep a
requirements.txtinstead and recreate the environment. - Moving or copying a venv. The docs say not to; recreate it in the new location.
- Using
--system-site-packagesas a shortcut. It gives the venv access to the system site-packages. Only use it when you really need those packages.
Quick reference#
| Goal | Command |
|---|---|
| Project libraries | python3 -m venv .venv, then source .venv/bin/activate, then pip install xyz |
| Run without activating | .venv/bin/python -m pip install xyz |
| A command-line app | pipx install xyz |
| System-wide package (Debian style) | sudo apt install python3-xyz |
venv module missing |
sudo apt install python3-full |
| Check you're in a venv | python -c "import sys; print(sys.prefix != sys.base_prefix)" |
| Last resort | pip install --break-system-packages xyz |
Checklist:
- Read the distro message in the error; it names the right commands.
- Library for your own code: venv.
- Tool you just want to run: pipx.
- Needed by the OS or a service: the distro package.
- Flag only after the above, and only where you can recover.
For how venvs work in detail, see the venv documentation.
Quick answers
What is a managed environment in Python?
It's a Python interpreter whose packages are owned by an external tool such as the OS package manager. The distributor marks it with an EXTERNALLY-MANAGED file, and pip refuses to change its global packages unless you override it.
How do I fix externally-managed-environment without breaking my system?
Create a virtual environment with python3 -m venv .venv, activate it, and run pip inside it. For command-line apps, use pipx install instead. Neither one touches the system Python.
Is it safe to use --break-system-packages?
It's a risky override, not a fix. It lets pip write into the system Python, which can interfere with OS tools that depend on it. Keep it as a last resort, and prefer a venv, pipx or the distro's own package.
Why does pip work on some machines but give this error on others?
The check is opt-in. A Python built from upstream sources, or from a distro that doesn't ship the marker file, installs as before. Debian and its derivatives, among others, ship the marker.
Did this solve it?
One tap. No account.
Sorry about that. What was missing?
from 0 readers
Saved you an hour? Send a tip.
USDC or ETH on Base. Keeps the notes free and the examples running.
0x9dFD2Ee86182f92464b50809C6702B999a0Cd54f
On a computer? Scan the code with your phone wallet, or copy the address.
USDC or ETH on Base works best. Other tokens on Base, Ethereum or Arbitrum also reach this address. Tips are optional and unlock nothing; every guide stays free.
Discussion
Start the discussion
Next note