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
- Run the editor manually on the file path pip reports to see the real error.
- Verify the editor works in the current shell: `$EDITOR /tmp/test.txt`.
- Ensure the config file and its directory are writable.
- Pass an explicit editor with `--editor` that is known to work in this environment.
- 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
- Confirm $EDITOR/$VISUAL works in the current shell before relying on `pip config edit`.
- Pass `--editor` explicitly with a terminal-friendly binary in non-interactive shells.
- Ensure the config file is writable by the editor process.
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
- Could not determine editor to use.
- Need exactly one file to operate upon (--user, --site, --glo
- Could not determine appropriate file.
- Got unexpected number of arguments, expected {n}. (example:
- Internal Error.
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/142725f82f06a9ac.
Report an issue: GitHub.