Skip to content

FIX: Include the exception type when a scenario fails to start - #2521

Open
varunj-msft wants to merge 1 commit into
microsoft:mainfrom
varunj-msft:varunj-msft/v1.1.0-Release-Start-Error-Message
Open

FIX: Include the exception type when a scenario fails to start#2521
varunj-msft wants to merge 1 commit into
microsoft:mainfrom
varunj-msft:varunj-msft/v1.1.0-Release-Start-Error-Message

Conversation

@varunj-msft

Copy link
Copy Markdown
Contributor

Description

When starting a scenario run failed, the CLI printed Error starting scenario: with nothing after the colon.

httpx.ReadTimeout carries no message, so str(exc) is the empty string, and the one piece of information the user needed — that this was a timeout, not a bad scenario name or a missing target — was the one piece that got dropped.

This is not hypothetical. It is the exact output the End to End Tests produce today when the server takes longer to start a run than the client's read timeout allows, and it is a large part of why those failures were so hard to attribute.

Both start-run failure paths, in pyrit_scan and pyrit_shell, now go through _print_cli_exception, which the CLI already uses elsewhere for exactly this reason. It reports the exception class, falls back to repr() when str() is empty, and has a dedicated branch for ReadTimeout. The same failure now reads:

ERROR: The scenario could not be started.

Error (ReadTimeout): server did not respond in time. Pass '--request-timeout <seconds>' to wait longer, or check the server logs for a blocked event loop.

That version names the failure, gives the flag that changes it, and points at the server logs — the two things you would actually do next. Both call sites are fixed, so the behaviour is the same however the run was started.

Part of the v1.1.0 release wave with #2510, #2511 and #2512.

Tests and Documentation

Two new tests, one per entry point, both covering the ReadTimeout case specifically. They assert that the exception type and the --request-timeout hint both reach the user even though the exception stringifies to the empty string:

  • test_main_start_scenario_read_timeout_reports_type_and_hint in tests/unit/cli/test_pyrit_scan.py
  • test_run_start_failure_read_timeout_reports_type_and_hint in tests/unit/cli/test_pyrit_shell.py

The existing shell test for a generic start failure was updated to assert on the new format, Error (RuntimeError): nope, which keeps the message content covered rather than only the prefix.

Ran pytest tests/unit/cli/test_pyrit_scan.py tests/unit/cli/test_pyrit_shell.py: 234 passed.

No documentation changes. This changes console output only, and no doc or notebook contains this error string. JupyText was not run and is not applicable: no notebooks or code samples are affected.

@hannahwestra25 hannahwestra25 self-assigned this Sep 1, 2026
Comment thread pyrit/cli/pyrit_shell.py
try:
run = self._run_async(self._api_client.start_scenario_run_async(request=request))
except Exception as exc:
print(f"Error starting scenario: {exc}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: move import to 429

Comment thread pyrit/cli/pyrit_shell.py Outdated
from pyrit.cli.pyrit_scan import _print_cli_exception

print("\nERROR: The scenario could not be started.")
_print_cli_exception(exc=exc)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cp pointed out that _print_cli_exception tells users with a ReadTimeout to pass --request-timeout, but pyrit_shell doesn't accept or forwards that option, so the guidance is deceiving & we should provide some shell / scan specific guidance

httpx.ReadTimeout carries no message, so str(exc) is the empty string and the
scenario start failure printed "Error starting scenario: " with nothing after
it. That is the exact failure the end-to-end tests hit when the server takes
longer than the client read timeout to start a run, and it gave no indication
of what went wrong.

Route both start-run failure paths through _print_cli_exception, which the CLI
already uses elsewhere. It reports the exception class and falls back to repr()
when str() is empty.

The ReadTimeout hint names --request-timeout, which only pyrit_scan accepts, so
the shell asks for it explicitly and gets the part of the hint it can act on.
Advising a shell user to pass an option its parser rejects would be worse than
the empty message this replaces.
@varunj-msft
varunj-msft force-pushed the varunj-msft/v1.1.0-Release-Start-Error-Message branch from c1d4b40 to b9f5223 Compare September 1, 2026 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants