Blog
3 min read

pip "error: externally-managed-environment": What It Means and How to Fix It

Newer Linux distributions and Homebrew stop pip from installing packages into the system Python, to protect the operating system. Why it happens, and the right fixes: a virtual environment, uv, or pipx for tools — and why --break-system-packages is a last resort.

error: externally-managed-environment

× This environment is externally managed
╰─> 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.

You ran pip install something and Python refused. You'll see this on Ubuntu 23.04+, Debian 12+, recent Fedora, Homebrew Python on macOS, and other systems.

Why it happens

The operating system uses Python for its own tools. If you pip install packages into that same Python, you can overwrite or break the versions the system relies on. Distributions now mark their Python as externally managed (a standard called PEP 668) so pip refuses to touch it.

It's not a bug. It's telling you to install packages somewhere else.

Fix 1 (best): use a virtual environment

A virtual environment is a private copy of Python for your project. Install anything you like into it without affecting the system. (Python virtual environments)

python3 -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install requests

On Debian/Ubuntu, you may first need:

sudo apt install python3-venv

Remember to activate the environment each time you open a new terminal (or let your editor do it). Add .venv/ to .gitignore. (.gitignore explained)

Fix 2: use uv

uv is a fast Python package and project manager that handles virtual environments for you:

uv venv
uv pip install requests
# or, for a project:
uv init
uv add requests
uv run app.py

uv run uses the project's environment automatically — no activating needed.

Fix 3: for command-line tools, use pipx

If you want a Python program available everywhere (like httpie, black or yt-dlp), install it with pipx, which gives each tool its own isolated environment:

sudo apt install pipx     # or: brew install pipx
pipx ensurepath
pipx install httpie

uv tool install httpie does the same thing.

Fix 4: the system package

For a library the OS packages, install it through the system package manager:

sudo apt install python3-requests

Fine for scripts that only use common libraries, but versions are often older and the selection is limited.

The escape hatch: --break-system-packages

pip install --break-system-packages requests

This overrides the protection. The name is honest: it can break system tools, and a future OS update can break your packages. Reasonable inside a throwaway container where nothing else uses that Python; avoid it on your laptop or a server.

Similarly, deleting the EXTERNALLY-MANAGED marker file "works" but removes the protection for everything.

In Docker

In a container built just for your app, the official python images aren't externally managed, so pip works normally. If you build from a Debian/Ubuntu base and install Python with apt, use a virtual environment inside the image, or use uv. (Dockerfile explained)

Then: record your dependencies

Once you're in a virtual environment, keep a list of what the project needs so it can be recreated anywhere:

pip freeze > requirements.txt

(requirements.txt explained)


EasySpawn gives each Python app its own environment on your server, installed from your requirements on every deploy — no fighting the system Python. See how it works or join the waitlist.

Related: Python Virtual Environments · ModuleNotFoundError: No module named · requirements.txt Explained · What Is Python?

Keep reading