TUI startup errors invisible — alt-screen tears down before user can read them #6
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
When
ratatoskr.tui'son_mountencounters an error during session setup(
AgentNotFound,SessionApiFailed, network error duringcreate_session), it writes a labeled[error_kind] ...line to theRichLog widget and calls
self.exit(<code>). The Textual app exits, thealt-screen tears down, and the user is left looking at a blank terminal —
the labeled line was written to the RichLog widget which only exists inside
the alt-screen. Exit code is set correctly, but there's no visible
diagnostic.
Surfaced during manual smoke 2026-05-21:
ratatoskr --new --agent lofn(which hits the issue #5 bug, 422 from server) blanks the screen for ~200ms
then quits with exit code 20. No visible diagnostic; the operator's only
recourse is to re-run the same flow under
--send(which writes errors toreal stderr that survives) to see what happened.
The
--sendmode handles this class of error correctly: stderr labels goto real stderr, which is the operator's terminal directly, not the
alt-screen. The TUI's flow violates the "errors should be visible to the
user" expectation that
--sendupholds.Solution
Recommendation: Option A — move session-create out of
on_mountandinto
run_tui(sync, BEFORE App.run() opens the alt-screen). Surfaceerrors to stderr at the
run_tuilayer; only enter the alt-screen aftersession-create succeeds.
This aligns the TUI's startup-error UX with the CLI's: failures before the
event loop opens print to stderr; failures during streaming render in
the alt-screen (where mid-session errors per INV-008 already go).
Implementation shape:
RatatoskrApp.__init__gainssession_id/agent_idparameters (pre-resolved).
on_mountno longer creates the session; it just opens theAsyncClient and populates the identity widgets.
Alternative options considered + rejected:
app.run()returns non-zero.Requires the App to expose its log content after exit; relies on widget
content surviving teardown. Adds a post-exit dump step that feels like
workaround.
~/.cache/ratatoskr/last-error.log.Rejected per design-brief §8d ("no cross-process resume, no config dir").
Out of scope (this issue)
surface). Each side pane is its own issue.
RichLog and return to idle per INV-008's "errors don't exit the app"
contract; the user reads them in the TUI. Only startup-phase errors
need pre-alt-screen visibility.
Benefits
--sendtodiagnose. Fixes the "screen blanks then quits" UX surfaced 2026-05-21.
bugs) before the alt-screen masks them.
failures inside App.run() (mid-stream) → RichLog per INV-008.
Acceptance
run_tuiSTEPS expanded with the pre-App.run() session-resolve step;
RatatoskrApp.__init__signature widened;on_mountSTEPS narrowed to client-open + identity-widget-populate.TestAppMounttests no longer drive session-create throughon_mount(it's gone); newTestRunTuitests cover the pre-App.run()error paths via stderr capture.
ratatoskr --new --agent <nonexistent>produces a visible[agent_not_found]line on stderr; no screen-blanking artifact.Dependencies
ratatoskr.tuishell) — landed on main; this issue amends itscontract.
wrong-input flow for per-user agents becomes 422-from-server which #6
must surface. But #6 is independent in scope; either can land first.
Closed — shipped. TUI startup error visibility implemented via TDD, two Volva rounds (commit
804c2df). _resolve_then_run routes pre-flight errors to stderr BEFORE alt-screen opens.