Skip to content

fix(opencode): answer a failed TUI worker request instead of hanging - #54936

Merged
rekram1-node merged 2 commits into
anomalyco:v1from
Nowaker:rpc-error-reply
Oct 27, 2026
Merged

rekram1-node merged 2 commits into
anomalyco:v1from
Nowaker:rpc-error-reply

Conversation

@Nowaker

@Nowaker Nowaker commented Oct 12, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #54934

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The TUI talks to its server worker over a small RPC channel and waits on it before it draws anything, for example to start the listener for --port. When the worker's handler threw, Rpc.listen never posted a reply (the worker's unhandledRejection handler swallows the error), so the TUI's client.call() never settled. With opencode --port 4096 and the port already taken, that is a blank terminal forever, with no hint why.

Now Rpc.listen answers a failed request with the error's message and Rpc.client rejects the pending call with it. The failure reaches the TUI's existing error handling, and opencode exits with Failed to start server. Is port 4096 in use?. Server.listen rejects with a ServeError that has no message of its own and names the port in its cause, so when an error has no message, the cause's is sent instead.

Related: #34981 and #42885 cover a worker that dies with calls pending. This covers a worker that stays up but whose handler throws.

How did you verify your code works?

  • New test/util/rpc.test.ts drives a real worker whose methods return, throw, reject, and throw with only a cause. On v1 without the change, 3 of the 4 tests fail because those calls get no reply; with it, all 4 pass.
  • opencode --port <port> while another process holds the port: before, the screen is still blank 20 s later; after, opencode exits with code 1 and the message above.
  • bun typecheck in packages/opencode is clean, and test/cli/tui/thread.test.ts passes.

Screenshots / recordings

Not a UI change; the visible difference is the error message above.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

This PR is AI generated, but under direct supervision and on request of @Nowaker.

A method behind the TUI worker's RPC channel that threw never got a
reply, so the caller's promise never settled. The TUI waits on that
channel before it draws anything, so for example `opencode --port 4096`
with port 4096 already taken stayed on a blank screen forever.

The worker now answers a failed request with the error's message, or
its cause's when it has none (a taken port fails with an empty
ServeError whose cause names the port), and the call rejects with it,
so opencode exits with that message.
@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 12, 2026
A new feature record covers the TUI worker's error replies (c50b736,
upstream issue anomalyco#54934 and PR anomalyco#54936 against v1). The session maintenance
record gains the bounded write-lock retry at startup (22e6326) in its
safety contract and timeline. The 2026-10-12 session record has the
cause, the reproduction on vt-243 against vt-248 with several opencode
processes starting on a locked database, and the installs on both hosts.

AI-Tool: opencode 1.18.34-vt-128-907b3bc518
AI-Model: anthropic/claude-opus-5-5
AI-Variant: max
AI-Platform: linux
AI-Harness: Vibeterm a2d1757
AI-Session-ID: ses_eebf9a83fffeIQQwW9gVFo5jaO
@jlongster

Copy link
Copy Markdown
Contributor

thanks!

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.

3 participants