pypa/pip · warning · PipError

Editor Subprocess exited with exit code {returncode}

Error message

Editor Subprocess exited with exit code {returncode}

What it means

Raised by `pip config edit` when the editor subprocess returns a non-zero exit code. open_in_editor at configuration.py:247 runs `subprocess.check_call(f'{editor} "{fname}"', shell=True)`; on CalledProcessError (non-zero return) it wraps the returncode in a PipError at configuration.py:254.

Source

Thrown at src/pip/_internal/commands/configuration.py:254

        fname = self.configuration.get_file_to_edit()
        if fname is None:
            raise PipError("Could not determine appropriate file.")
        elif '"' in fname:
            # This shouldn't happen, unless we see a username like that.
            # If that happens, we'd appreciate a pull request fixing this.
            raise PipError(
                f'Can not open an editor for a file name containing "\n{fname}'
            )

        try:
            subprocess.check_call(f'{editor} "{fname}"', shell=True)
        except FileNotFoundError as e:
            if not e.filename:
                e.filename = editor
            raise
        except subprocess.CalledProcessError as e:
            raise PipError(f"Editor Subprocess exited with exit code {e.returncode}")

    def _get_n_args(self, args: list[str], example: str, n: int) -> Any:
        """Helper to make sure the command got the right number of arguments"""
        if len(args) != n:
            msg = (
                f"Got unexpected number of arguments, expected {n}. "
                f'(example: "{get_prog()} config {example}")'
            )
            raise PipError(msg)

        if n == 1:
            return args[0]
        else:
            return args

    def _save_configuration(self) -> None:
        # We successfully ran a modifying command. Need to save the
        # configuration.

View on GitHub (pinned to f399c37189)

Solutions

  1. Run the editor manually on the file path pip reports to see the real error.
  2. Verify the editor works in the current shell: `$EDITOR /tmp/test.txt`.
  3. Ensure the config file and its directory are writable.
  4. Pass an explicit editor with `--editor` that is known to work in this environment.
  5. If the editor is GUI-only, ensure DISPLAY/Wayland is available or use a terminal editor.

Example fix

// before
EDITOR=code pip config edit   # code exits non-zero when not attached
// after
EDITOR=nano pip config edit
Defensive patterns

Strategy: try-catch

Validate before calling

# Verify the editor launches cleanly before pip config edit
import shutil, subprocess, os

def editor_ok(editor=None):
    ed = editor or os.environ.get("VISUAL") or os.environ.get("EDITOR")
    if not ed or not shutil.which(ed.split()[0]):
        return False
    return True

Try / catch

# subprocess approach to surface editor errors
import subprocess
try:
    subprocess.check_call(["pip", "config", "edit"])
except subprocess.CalledProcessError:
    # editor exited non-zero; run it directly to see the real error
    editor = os.environ.get("VISUAL") or os.environ.get("EDITOR")
    subprocess.call([editor, config_file_path()])

Prevention

When it happens

Trigger: The editor (from --editor, $VISUAL, or $EDITOR) launches but exits abnormally — e.g. the user quits with an error code, the editor hits a permission error on the file, or the editor command is malformed yet succeeds in starting.

Common situations: EDITOR points to a binary that errors on the file (permissions, read-only filesystem), the editor prints errors and exits non-zero, or a wrapper script around the editor fails. Common with editors invoked without a terminal in non-interactive shells.

Related errors


AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08). Data as JSON: /api/errors/142725f82f06a9ac. Report an issue: GitHub.