Skip to content

TUI blank screen after backend Instance disposal — unbounded retry, stale context, no session re-sync #16545

Closed as not planned

Description

@sjawhar

Description

When the backend Instance is disposed while the TUI is active (e.g., during serve mode idle timeout or reload), several recovery bugs can leave the TUI in a broken state:

  1. No session re-sync: After disposal and re-bootstrap, the currently viewed session's data goes stale. fullSyncedSessions is cleared but the active session isn't re-fetched, so the user sees frozen/incomplete content until they navigate away and back.

  2. Unbounded retry loop: If re-bootstrap fails after disposal, the catch handler retries with a fixed 2s delay and no maximum — spinning indefinitely, consuming CPU and generating log spam.

  3. No concurrency guard on retries: Rapid disposal events (e.g., from disposeAll()) can trigger overlapping bootstrap calls with no generation tracking, so stale retries from earlier disposals continue running alongside newer ones.

  4. Stale Instance context in event stream: Instance.provide() wraps the entire event stream while loop, so after disposal the reconnect loop runs with a stale context reference instead of getting fresh context per iteration.

  5. Unconditional event stream startup: The worker starts startEventStream(process.cwd()) at module load regardless of transport mode. In external transport mode this is unnecessary and the directory should come from the thread.

  6. Event stream not restarted on reload: reload() calls disposeAll() but doesn't restart the event stream, relying on timing-sensitive SSE reconnect behavior.

Steps to Reproduce

  1. Start the TUI in serve mode
  2. Wait for idle timeout to dispose the Instance (or trigger reload())
  3. Observe blank screen or stale session data
  4. If bootstrap fails, observe unbounded retry in logs

Expected Behavior

  • After disposal, the TUI should re-bootstrap and automatically refresh the current session's data
  • Failed re-bootstraps should retry with bounded exponential backoff (not forever)
  • Stale retry chains should be cancelled when newer disposals arrive
  • Each event stream reconnect should get fresh Instance context
  • Event stream should only start when appropriate (not in external transport mode)
  • reload() should explicitly restart the event stream

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Mar 8, 2026
  2. assigned and unassigned on Apr 26, 2026
  3. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  4. github-actions commented on Jul 3, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions