Skip to main content
DevOps Insightsguides & answers

Python (pip) · troubleshooting

error: externally-managed-environment

pip refuses to install into a Python that the operating system or Homebrew manages, so a system update cannot break it. Install into a virtual environment, use pipx for command-line tools, or apt install python3-NAME. --break-system-packages only overrides the guard.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 10 sections

Before you start

  • A shell where pip install fails, or a Dockerfile or CI job that runs it.
  • python3 -m venv, which on Debian and Ubuntu needs the python3-venv package (python3-full includes it).

Run this first

step 1 of 2
python3 -c 'import sys; print(sys.executable, sys.prefix == sys.base_prefix)'

Look for /usr/bin/python3 and True means the system Python, outside a venv

Shows which Python pip belongs to, and whether it is a virtual environment.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

What are you installing, and where?

Cause space

3 of 3 still possible

  • Installing a project's dependencies into the system PythonCommon
  • Installing a command-line tool globallyCommon
  • A Dockerfile based on ubuntu or debian runs pip installCommon

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Check it with a tool

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    python3 -c 'import sys; print(sys.executable, sys.prefix == sys.base_prefix)'

    Shows which Python pip belongs to, and whether it is a virtual environment.

    Look for /usr/bin/python3 and True means the system Python, outside a venv

  2. Step 2

    python3 -m pip --version

    Confirms the pip that runs belongs to that same interpreter.

    Look for A path under /usr/lib/python3 (system) or under .venv (yours)

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

Installing a project's dependencies into the system Python

Common

pip install -r requirements.txt, run with the system python3 on Debian 12+, Ubuntu 24.04+ or Homebrew, targets the managed environment and is refused.

Confirm

python3 -c 'import sys,sysconfig,os; print(sys.prefix == sys.base_prefix, os.path.exists(os.path.join(sysconfig.get_path("stdlib"), "EXTERNALLY-MANAGED")))'

True True: not in a venv, and the Python is marked

Fix

  • Create a virtual environment for the project and install into it: python3 -m venv .venv, then .venv/bin/pip install -r requirements.txt, and run the project with .venv/bin/python.
  • On Debian or Ubuntu, if venv is missing, install it first: sudo apt install python3-venv (or python3-full).
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt

Activate with source .venv/bin/activate if you prefer plain python and pip afterwards.

Installing a command-line tool globally

Common

Tools such as ansible, awscli or pre-commit were often installed with pip install --user or sudo pip. Both are refused now.

Confirm

pip install --user NAME

The same externally-managed-environment error

Fix

  • Install the tool with pipx, which gives it its own environment: pipx install NAME (on Debian and Ubuntu sudo apt install pipx; on macOS brew install pipx).
  • Or use the distribution's package if it has one: sudo apt install python3-NAME or the tool's own apt package.

A Dockerfile based on ubuntu or debian runs pip install

Common

The marker is in the image too, so a RUN pip install that worked on ubuntu:22.04 or debian:11 fails after the base image moves to a newer release.

Confirm

docker run --rm IMAGE sh -c 'ls /usr/lib/python3*/EXTERNALLY-MANAGED'

The file exists in the base image

Fix

  • Create a venv in the image and put it first on PATH: RUN python3 -m venv /opt/venv then ENV PATH=/opt/venv/bin:$PATH, and later RUN pip install -r requirements.txt uses it.
  • Or start from an official python image (python:3.x-slim), whose Python is not managed by apt.
  • Only for throwaway images where nothing else uses the system Python: pip install --break-system-packages.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

On Debian 12, Ubuntu 24.04 and later, and Homebrew, the system Python belongs to the package manager: apt or brew installed its libraries and expects to update them. If pip also changed them, one tool could silently break the other, including tools the OS itself relies on. So that Python now carries a marker file, and pip stops with this error instead of installing. The fix is to give your project its own Python environment.

Words used on this page

Externally managed
A Python installation whose packages belong to another package manager (apt, brew). It is marked by an EXTERNALLY-MANAGED file next to the standard library.
Virtual environment (venv)
A private Python environment with its own site-packages. pip ignores the marker inside one, so installs work there.
pipx
A tool that installs each Python command-line application into its own virtual environment and puts the command on your PATH.
PEP 668
The Python standard that defines the marker file and tells installers like pip to refuse outside a virtual environment.
What is actually happening

PEP 668 tells installers to refuse when two things are true: they are not running in a virtual environment (sys.prefix equals sys.base_prefix), and the standard library directory contains a file called EXTERNALLY-MANAGED. pip then prints the file's message under This environment is externally managed.

Debian 12 introduced the marker (its release notes have a section for it), and Ubuntu releases since then ship it, including 24.04 and 26.04. Homebrew marks its Python too. The Debian message suggests apt install python3-xyz, a venv, or pipx.

GitHub-hosted Ubuntu runners are the exception that confuses people: their images write break-system-packages = true to /etc/pip.conf on every Ubuntu version except 22.04, so pip install works in a workflow and then fails in a Docker image or on a self-hosted machine built from the same Ubuntu.

Containers are not exempt: PEP 668 recommends that distributions keep the marker in their container images, so FROM ubuntu:24.04 plus apt install python3-pip plus pip install fails during docker build.

How to tell this is your problem
WhereWhat you see
pip installerror: 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.
The same outputnote: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
docker buildA RUN pip install step fails in an image built FROM ubuntu:24.04 or debian:12

How to know it is actually fixed

  • .venv/bin/pip install -r requirements.txt completes, and .venv/bin/python -c 'import NAME' works.
  • pipx list shows the tools you installed with pipx, each in its own environment.

Stopping it happening again

  • Give every project a venv (or a tool such as uv or Poetry that creates one), and run it from there in CI and in production.
  • In Dockerfiles, create the venv in the image, so the build does not depend on how the base image marks its Python.
  • Do not copy break-system-packages = true from CI runner images into servers or images you maintain.

Security considerations

  • --break-system-packages, or break-system-packages = true in pip.conf, lets pip overwrite libraries the OS installed. On a server or a laptop that can break apt-installed tools and survive until the next upgrade. Prefer a venv.
  • Never use sudo pip install. It writes as root into directories apt owns, which is exactly what the marker is there to stop.
  • A virtual environment also keeps a project's dependencies, and their vulnerabilities, from leaking into everything else on the machine.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it