connectrpc / examples-es

Examples for using Connect with various TypeScript web frameworks and tooling.
https://connectrpc.com/
Apache License 2.0
122 stars 23 forks source link

React Native - Parsing Server Error Response gives "missing trailer" #2135

Open anmho opened 1 week ago

anmho commented 1 week ago

Hi all, I am currently working off of a repo inspired by the react-native example in this repo. Right now, I'm struggling to get errors to be parsed correctly using the React-Native client and a Go server.

When an error is returned from the server, the React Native client custom transport throws a missing trailers issue. curl, grpcurl, and Postman each handle and parse the error correctly.

Fields of the error thrown:

Cause: missing trailer
Code: 2
Details: 
FindDetails: function findDetails(a0) { [bytecode] }
Message: [unknown] missing trailer
Metadata: [object Object]
Name: ConnectError
RawMessage: missing trailer

This seems to be an issue with the provided custom transport implementation since thats where the error is thrown.

My custom-transport.ts is exactly as shown in the React Native example.

Reproduce:

  1. Follow setup steps in: https://connectrpc.com/docs/web/supported-browsers-and-frameworks/#react-native and https://github.com/connectrpc/examples-es/blob/main/react-native/README.md
  2. Call any RPC that returns an error to the caller.
  3. Client will throw an error with the message "missing trailer"

Example repo: Clone this repository Run make gen Run npm run ios in /react-native Run Dev Server using make watch in the project root.

timostamm commented 8 hours ago

Hey Andrew, I think this is a bug in the custom transport implementation.

Usually, gRPC-web encodes trailers (which have the error information) in the body, but it can optionally send them as headers. It appears that the custom transport doesn't handle them correctly.

Can you try changing line 143?

https://github.com/connectrpc/examples-es/blob/cd9a4d1b3bc069b13a907880511b7cbb49cfb965/react-native/app/custom-transport.ts#L143

-         const { headerError } = validateResponse(response.status, response.headers);
+         const { headerError } = validateResponse(response.status, response.headers);
+         if (headerError !== undefined) {
+           throw headerError;
+         }

The behavior of the function was changed some time ago, and it seems we didn't update this call site. Sorry about that - unfortunately, it's not feasible to run the custom transport in the same test suite that other transports run, so we didn't catch it.

If this change works, a PR to fix the example would be much appreciated!