From 9547f3aa22ce21df7a443ec4636e03fc4db47a44 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Fri, 13 Feb 2026 00:50:46 -0800 Subject: [PATCH 1/3] Fix unhelpful KeyError when using invalid VIRTUALENV_DISCOVERY value When an invalid discovery method is specified via the VIRTUALENV_DISCOVERY environment variable, virtualenv now raises a clear ValueError listing all available discovery methods instead of showing a confusing KeyError. This improves the user experience by making it immediately clear what went wrong and what the valid options are, especially useful when the error appears in the middle of a long tox stacktrace. Fixes #2896 --- src/virtualenv/run/plugin/discovery.py | 7 +++++++ tests/unit/test_run.py | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/virtualenv/run/plugin/discovery.py b/src/virtualenv/run/plugin/discovery.py index 5e8b2392f..6c924718b 100644 --- a/src/virtualenv/run/plugin/discovery.py +++ b/src/virtualenv/run/plugin/discovery.py @@ -29,6 +29,13 @@ def get_discover(parser, args): help="interpreter discovery method", ) options, _ = parser.parse_known_args(args) + + # Check if the specified discovery method is valid + if options.discovery not in discover_types: + available = ", ".join(f"'{key}'" for key in sorted(discover_types.keys())) + msg = f"Invalid discovery method '{options.discovery}'. Available options: {available}" + raise ValueError(msg) + discover_class = discover_types[options.discovery] discover_class.add_parser_arguments(discovery_parser) options, _ = parser.parse_known_args(args, namespace=options) diff --git a/tests/unit/test_run.py b/tests/unit/test_run.py index b61731d57..707954633 100644 --- a/tests/unit/test_run.py +++ b/tests/unit/test_run.py @@ -41,3 +41,15 @@ def test_logging_setup(caplog, on): assert not caplog.records else: assert caplog.records + + +def test_invalid_discovery_method_via_env(monkeypatch): + """Test that an invalid discovery method via env var raises a helpful error.""" + monkeypatch.setenv("VIRTUALENV_DISCOVERY", "pyenv") + with pytest.raises(ValueError) as exc_info: + session_via_cli(["env"]) + + error_message = str(exc_info.value) + assert "Invalid discovery method 'pyenv'" in error_message + assert "Available options:" in error_message + assert "'builtin'" in error_message From 9c20fce157eb753a25bc39d6808133ed4a3a8064 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 08:52:40 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/virtualenv/run/plugin/discovery.py | 4 ++-- tests/unit/test_run.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/virtualenv/run/plugin/discovery.py b/src/virtualenv/run/plugin/discovery.py index 6c924718b..55e730cb5 100644 --- a/src/virtualenv/run/plugin/discovery.py +++ b/src/virtualenv/run/plugin/discovery.py @@ -29,13 +29,13 @@ def get_discover(parser, args): help="interpreter discovery method", ) options, _ = parser.parse_known_args(args) - + # Check if the specified discovery method is valid if options.discovery not in discover_types: available = ", ".join(f"'{key}'" for key in sorted(discover_types.keys())) msg = f"Invalid discovery method '{options.discovery}'. Available options: {available}" raise ValueError(msg) - + discover_class = discover_types[options.discovery] discover_class.add_parser_arguments(discovery_parser) options, _ = parser.parse_known_args(args, namespace=options) diff --git a/tests/unit/test_run.py b/tests/unit/test_run.py index 707954633..e86480e36 100644 --- a/tests/unit/test_run.py +++ b/tests/unit/test_run.py @@ -48,7 +48,7 @@ def test_invalid_discovery_method_via_env(monkeypatch): monkeypatch.setenv("VIRTUALENV_DISCOVERY", "pyenv") with pytest.raises(ValueError) as exc_info: session_via_cli(["env"]) - + error_message = str(exc_info.value) assert "Invalid discovery method 'pyenv'" in error_message assert "Available options:" in error_message From ad2facee025ce8e372826421e36e93a1562857c0 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Fri, 13 Feb 2026 19:37:25 -0800 Subject: [PATCH 3/3] Fix ruff PT011: add match parameter to pytest.raises --- tests/unit/test_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_run.py b/tests/unit/test_run.py index e86480e36..1afaab331 100644 --- a/tests/unit/test_run.py +++ b/tests/unit/test_run.py @@ -46,7 +46,7 @@ def test_logging_setup(caplog, on): def test_invalid_discovery_method_via_env(monkeypatch): """Test that an invalid discovery method via env var raises a helpful error.""" monkeypatch.setenv("VIRTUALENV_DISCOVERY", "pyenv") - with pytest.raises(ValueError) as exc_info: + with pytest.raises(ValueError, match=r"Invalid discovery method 'pyenv'") as exc_info: session_via_cli(["env"]) error_message = str(exc_info.value)