{"record":{"id":"142725f82f06a9ac","repo":"pypa/pip","slug":"editor-subprocess-exited-with-exit-code-returncod","errorCode":null,"errorMessage":"Editor Subprocess exited with exit code {returncode}","messagePattern":"Editor Subprocess exited with exit code (.+?)","errorType":"exception","errorClass":"PipError","httpStatus":null,"severity":"warning","filePath":"src/pip/_internal/commands/configuration.py","lineNumber":254,"sourceCode":"\n        fname = self.configuration.get_file_to_edit()\n        if fname is None:\n            raise PipError(\"Could not determine appropriate file.\")\n        elif '\"' in fname:\n            # This shouldn't happen, unless we see a username like that.\n            # If that happens, we'd appreciate a pull request fixing this.\n            raise PipError(\n                f'Can not open an editor for a file name containing \"\\n{fname}'\n            )\n\n        try:\n            subprocess.check_call(f'{editor} \"{fname}\"', shell=True)\n        except FileNotFoundError as e:\n            if not e.filename:\n                e.filename = editor\n            raise\n        except subprocess.CalledProcessError as e:\n            raise PipError(f\"Editor Subprocess exited with exit code {e.returncode}\")\n\n    def _get_n_args(self, args: list[str], example: str, n: int) -> Any:\n        \"\"\"Helper to make sure the command got the right number of arguments\"\"\"\n        if len(args) != n:\n            msg = (\n                f\"Got unexpected number of arguments, expected {n}. \"\n                f'(example: \"{get_prog()} config {example}\")'\n            )\n            raise PipError(msg)\n\n        if n == 1:\n            return args[0]\n        else:\n            return args\n\n    def _save_configuration(self) -> None:\n        # We successfully ran a modifying command. Need to save the\n        # configuration.","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_internal/commands/configuration.py#L236-L272","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nEDITOR=code pip config edit   # code exits non-zero when not attached\n// after\nEDITOR=nano pip config edit","handlingStrategy":"try-catch","validationCode":"# Verify the editor launches cleanly before pip config edit\nimport shutil, subprocess, os\n\ndef editor_ok(editor=None):\n    ed = editor or os.environ.get(\"VISUAL\") or os.environ.get(\"EDITOR\")\n    if not ed or not shutil.which(ed.split()[0]):\n        return False\n    return True\n","typeGuard":null,"tryCatchPattern":"# subprocess approach to surface editor errors\nimport subprocess\ntry:\n    subprocess.check_call([\"pip\", \"config\", \"edit\"])\nexcept subprocess.CalledProcessError:\n    # editor exited non-zero; run it directly to see the real error\n    editor = os.environ.get(\"VISUAL\") or os.environ.get(\"EDITOR\")\n    subprocess.call([editor, config_file_path()])\n","preventionTips":["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."],"tags":["cli","pip-config","subprocess","editor","configuration"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}