Skip to content

bug: Server Closed Subscriptions Don't Update Websocket Client Connection State #6962

@noseworthy

Description

@noseworthy

Provide environment information

  System:
    OS: macOS 15.7
    CPU: (10) arm64 Apple M1 Max
    Memory: 113.00 MB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.18.1 - ~/n/bin/node
    Yarn: 4.9.2 - ~/n/bin/yarn
    npm: 10.8.2 - ~/n/bin/npm
    bun: 1.2.22 - /opt/homebrew/bin/bun
  Browsers:
    Edge: 140.0.3485.81
    Safari: 26.0.1
  npmPackages:
    @tanstack/react-query: 5.90.1 => 5.90.1
    @trpc/client: 11.5.1 => 11.5.1
    @trpc/server: 11.5.1 => 11.5.1
    @trpc/tanstack-react-query: 11.5.1 => 11.5.1
    react: 18.3.1 => 18.3.1
    typescript: 5.7.3 => 5.7.3

Describe the bug

When a subscription is closed on the server side when using @trpc/tanstack-react-query and using the wsLink and WebsocketClient from createWSClient(), I'm not seeing the subscription state change from pending => idle. The subscription always stays in the pending state. The websocket is still connected, it's just the subscription state itself that is inaccurate.

Most of our subscriptions have idle timeouts configured so that the server will close the connection after some period of inactivity. This works fine when using SSE or when using SSE or Websockets with @trpc/react-query, but when I tried migrating to @trpc/tanstack-react-query, we're seeing this behaviour. This is problematic for our application because we have a separate mutation that is called to kick off some work, the results of which are broadcast to the client over the subscription. We check the state of the subscription before submitting work, and if it's idle, we reconnect by calling reset() on the subscription. Since the status isn't updating, the subscription eventually stops and then the client is stuck never receiving events until they refresh.

Link to reproduction

https://stackblitz.com/edit/github-ebaymo2t?file=client%2Fsrc%2FSubscription.tsx

To reproduce

  1. Ensure that you're looking at the vite server by confirming the port "3000" in the url of the preview browser (https://githubebaymo2t-4gxi--3000--96435430.local-corp.webcontainer.io)
  2. Watch the logs from the backend server in the terminal. It should say "listening for events" when started.
  3. Click "Start" immediately.
  4. You should see events streaming from the backend to the browser
  5. Redo steps 3-4 a couple of times to ensure that you can regularly start the "worker" on the backend and get events.
  6. 5 seconds after the last event is recieved you should see "going idle" in the terminal. This will indicate that the server has closed the subscription using return
  7. Notice that the status in the browser still says "pending".
  8. If you click "start work" in the browser, you can see the events being generated by the server, but no events are making it to the browser, and the subscription status is still "pending".
  9. Refresh the browser
  10. Click "Start" immediately
  11. See the events streaming normally as before.

Since we rely on the subscription status to determine when to restart the subscription, the client gets broken when using websockets, @trpc/tanstack-react-query and subscriptions.

Additional information

No response

👨‍👧‍👦 Contributing

  • 🙋‍♂️ Yes, I'd be down to file a PR fixing this bug!

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions