pypa/pip · error · ValueError
Invalid value: on_returncode={on_returncode!r}
Error message
Invalid value: on_returncode={on_returncode!r} What it means
Defensive ValueError raised by pip's subprocess runner when the `on_returncode` argument is not one of the three allowed literals: 'raise', 'warn', or 'ignore'. It fires only when a subprocess the runner invoked actually exits non-zero and the supplied handling mode is unrecognized. The default is 'raise', so this only happens for callers passing a custom bad value.
Source
Thrown at src/pip/_internal/utils/subprocess.py:224
)
subprocess_logger.verbose(
"[bold magenta]cwd[/]: %s",
escape(cwd or "[inherit]"),
extra={"markup": True},
)
raise error
elif on_returncode == "warn":
subprocess_logger.warning(
'Command "%s" had error code %s in %s',
command_desc,
proc.returncode,
cwd,
)
elif on_returncode == "ignore":
pass
else:
raise ValueError(f"Invalid value: on_returncode={on_returncode!r}")
return output
def runner_with_spinner_message(message: str) -> Callable[..., None]:
"""Provide a subprocess_runner that shows a spinner message.
Intended for use with for BuildBackendHookCaller. Thus, the runner has
an API that matches what's expected by BuildBackendHookCaller.subprocess_runner.
"""
def runner(
cmd: list[str],
cwd: str | None = None,
extra_environ: Mapping[str, Any] | None = None,
) -> None:
with open_spinner(message) as spinner:
call_subprocess(
cmd,View on GitHub (pinned to d7d0d0a394)
Solutions
- Pass one of exactly 'raise', 'warn', or 'ignore' for on_returncode.
- If you need custom handling, leave on_returncode='raise' and catch the resulting InstallationSubprocessError yourself.
- Audit third-party plugins for typos in the on_returncode argument.
Example fix
// before runner.run(cmd, on_returncode="abort") // after runner.run(cmd, on_returncode="raise")
Defensive patterns
Strategy: type-guard
Validate before calling
ALLOWED = {'raise', 'warn', 'ignore'}
assert on_returncode in ALLOWED, f'on_returncode must be one of {ALLOWED}'
runner.run(cmd, on_returncode=on_returncode) Type guard
from typing import Literal
def is_valid_returncode(x: object) -> bool:
return x in ('raise', 'warn', 'ignore')
ValidReturnCode = Literal['raise', 'warn', 'ignore'] Try / catch
null
Prevention
- Use a Literal type so static checkers reject typos.
- Default to on_returncode='raise' and handle errors at the call site.
- Audit third-party callers of pip's runner for the allowed values.
When it happens
Trigger: Calling pip's internal subprocess runner (e.g. via BuildBackendHookCaller or a custom call site) with on_returncode set to a typo like 'raises', 'abort', 'fail', None, or an unexpected Enum. Only triggers if the subprocess actually returns non-zero.
Common situations: Third-party code subclassing or reusing pip's runner with a typo; passing a value intended for a different pip version's API.
Related errors
- Got invalid value for load_only - should be one of {}
- Too many arguments
- Need exactly one file to operate upon (--user, --site, --glo
- Editor Subprocess exited with exit code {e.returncode}
- Got unexpected number of arguments, expected {n}. (example:
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/6330065c40be809a.json.
Report an issue: GitHub.