You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A console run (incl. the tray→terminal fallback) aborts with exit 134 when the tool's Status getter throws #79
ConsoleRunner.Run prints its startup line through DescribeRun (TrayApp/ConsoleRunner.cs:91-100), which calls TrayAppDefinition.Describe() (TrayApp/TrayAppDefinition.cs:73):
publicstringDescribe()=>Status?.Invoke()??$"{DisplayName} is running";
Nothing guards the getter here. #62/#64 made --status survive a throwing getter by reading it through StatusReport.Read, and #25 covers the tray menu. The console path still calls it bare. The exception leaves Run after the finally runs OnStop, then leaves TrayAppBuilder.RunAsync, which has no handler, so the process dies with an unhandled exception. That breaks the 0/1/2 exit-code contract. The same path is reached from the fallback in RecoverFromTrayFailure, when the tray can't start and the run "stays in the terminal instead".
Reproduction
.Status(() => throw new InvalidOperationException("systemd-inhibit was not found on PATH")) with OnStart/OnStop, run with --no-tray --for 1s:
>>> OnStart
>>> OnStop
Unhandled exception. System.InvalidOperationException: systemd-inhibit was not found on PATH
at ktsu.TrayApp.TrayAppDefinition.Describe() in TrayAppDefinition.cs:line 73
at ktsu.TrayApp.ConsoleRunner.DescribeRun(...) in ConsoleRunner.cs:line 97
exit=134
Running with --tray and no DISPLAY gives the same result once it has printed "Staying in the terminal instead."
#62 gave the reason for its own fix: a getter is likely to throw for the same reason the tool can't work. A missing helper is exactly the case where the console fallback gets used, and there it crashes.
Suggested fix / acceptance criteria
Read the status in DescribeRun through StatusReport.Read(app.Status), or have Describe() catch non-fatal exceptions (FatalError.IsNotFatal). It then prints e.g. repro: error: <message>. Press Ctrl+C to stop.
A throwing getter never ends the process with an unhandled exception. The run either continues or returns exit code 1 with a message.
ConsoleRunnerTests.Run_WhenTheRunItselfThrows_StillStops currently expects the exception to propagate from Run. Adjust it, or add a test for a throwing Status specifically.
Category: Bug Priority: Medium. A throwing Status getter crashes console runs with exit 134 and breaks the 0/1/2 exit-code contract. As #62 argued, the getter is most likely to throw in exactly the environment where the tray→terminal fallback kicks in. The trigger is specific, and the fix is one line, routing through the existing StatusReport.Read.
Suggested area / assignment:ConsoleRunner.DescribeRun (TrayApp/ConsoleRunner.cs:91-100) or TrayAppDefinition.Describe() (TrayApp/TrayAppDefinition.cs:73), plus ConsoleRunnerTests.
Duplicates / in progress: Not a duplicate, but part of the same family as #24 (a throwing OnStop aborts a console run with exit 134) and #25 (throwing getters in the tray menu, now covered). #62/#64 fixed the same problem for --status. Fixing #24 and this one together would leave the console runner with one top-level non-fatal exception policy. No open PR covers it.
Next step: Read the status through StatusReport.Read(app.Status) in DescribeRun. Add a test for a throwing Status, and adjust Run_WhenTheRunItselfThrows_StillStops if its expectation changes.
Activity
matt-edmondson commentedon Nov 5, 2026
Triage
Category: Bug
Priority: Medium. A throwing
Statusgetter crashes console runs with exit 134 and breaks the 0/1/2 exit-code contract. As #62 argued, the getter is most likely to throw in exactly the environment where the tray→terminal fallback kicks in. The trigger is specific, and the fix is one line, routing through the existingStatusReport.Read.Suggested area / assignment:
ConsoleRunner.DescribeRun(TrayApp/ConsoleRunner.cs:91-100) orTrayAppDefinition.Describe()(TrayApp/TrayAppDefinition.cs:73), plusConsoleRunnerTests.Duplicates / in progress: Not a duplicate, but part of the same family as #24 (a throwing
OnStopaborts a console run with exit 134) and #25 (throwing getters in the tray menu, now covered). #62/#64 fixed the same problem for--status. Fixing #24 and this one together would leave the console runner with one top-level non-fatal exception policy. No open PR covers it.Next step: Read the status through
StatusReport.Read(app.Status)inDescribeRun. Add a test for a throwingStatus, and adjustRun_WhenTheRunItselfThrows_StillStopsif its expectation changes.Generated by Claude Code