Skip to content

Closing subscription from server results in client throwing "Operation ended Prematurely" #4135

@gunhaxxor

Description

@gunhaxxor

Provide environment information

System:
   OS: Linux 5.10 Ubuntu 20.04.5 LTS (Focal Fossa)
   CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
   Memory: 6.37 GB / 12.37 GB
   Container: Yes
   Shell: 5.0.17 - /bin/bash
 Binaries:
   Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
   Yarn: 1.22.15 - ~/.yarn/bin/yarn
   npm: 8.19.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
 Browsers:
   Chrome: 109.0.5414.119
 npmPackages:
   @trpc/client: ^10.8.1 => 10.8.1 
   @trpc/react-query: ^10.8.1 => 10.8.1 
   @trpc/server: ^10.8.1 => 10.8.1 
   typescript: ^4.8.3 => 4.9.4 

Describe the bug

Closing subscription (calling the observer's complete function) from server results in client throwing "Operation ended Prematurely".
Also rather well described here: #4060

Link to reproduction

https://stackblitz.com/edit/github-6nnmqf-bkqqby?file=src/client.ts&view=editor

To reproduce

// Somewhere earlier, outside the subscription route:
let onData: ((data: string) => void) | undefined = undefined;
let onComplete: (() => void) | undefined = undefined;

// Inside the subscription route
return observable<string>((emit) => {
  onData = emit.next;
  onComplete = emit.complete;

  return () => {
    onData = undefined;
    onComplete = undefined;
  };
});
    
// Later when server wants to close connection
onComplete?.();

Additional information

This is happening because the wsClient (actually the wsLink code) only accepts calls to the complete callback if it originates from the client (the userland code using the TRPC subscription, that is). This is achieved by using a isdone boolean which is only set to true when userland calls unsubscribe.

👨‍👧‍👦 Contributing

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

Metadata

Metadata

Assignees

No one assigned

    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