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
Comment thread pyrit/cli/pyrit_shell.py Outdated
@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
Comment thread pyrit/cli/pyrit_scan.py Outdated
@varunj-msft
varunj-msft force-pushed the varunj-msft/v1.1.0-Release-Start-Error-Message branch 4 times, most recently from 21ab94d to 7547ef9 Compare September 1, 2026 22:22
Comment thread pyrit/cli/pyrit_shell.py
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.

Handle the timeout at the entry points rather than teaching the shared printer
who its caller is. Only a call site knows what its request was doing and which
options its own CLI accepts. The printer keeps the hint it already had, which is
correct for the pyrit_scan verbs that still reach it, and pyrit_shell no longer
reaches it with a timeout at all, so it can never be told to pass an option its
parser rejects.

A read timeout while starting a run does not mean the run failed to start. The
server keeps initializing after the client stops waiting, and it writes the
scenario result before it answers, so the outcome is genuinely unknown. Both
start paths now say so and point at scenario-history, because retrying blindly
can start the run a second time. The results paths point back at
scenario-results for the same run instead, since that request is a plain read.

Give scenario-history and scenario-results the same treatment. Those are the
commands the timeout hints send people to, and they printed the bare exception,
so a read timeout there reported the empty message this change exists to fix.
@varunj-msft
varunj-msft force-pushed the varunj-msft/v1.1.0-Release-Start-Error-Message branch from 7547ef9 to 2772ec4 Compare September 1, 2026 23:55
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