Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to display error message when server returns 500 with react-query #503

Closed
sillykelvin opened this issue Jan 10, 2025 · 3 comments
Closed

Comments

@sillykelvin
Copy link

I have the following code:

...
import { MyService } from './gen/api/api_pb';
import { useQuery } from '@connectrpc/connect-query';

export default function Page() {
  const { isPending, error, data } = useQuery(MyService.method.sayHello, { ... });

  if (error) {
    return (
      <div>error.message</div>
    );
  }

  if (isPending) {
    return (
      <div>loading data</div>
    );
  }

  return (
    <div>{data}</div>
  );
}

I want to display data if the RPC succeeds, and display error if it fails. However:

  • it works as expected if server side returns data without error
  • when server side returns error (status 500 with error detail in body), the page is always displaying loading data, no error message displayed

I notice that the browser console reports an error, seems to be the call stack when 500 error occurs:

POST http://localhost:9999/api.MyService/sayHello 500 (Internal Server Error)
next            @ ... // a javascript source file link, the same below
runUnaryCall    @ ...
unary           @ ...
callUnaryMethod @ ...
(anonymous)     @ ...
fetchFn         @ ...
run             @ ...
(anonymous)     @ ...
...

And the js source file link on first line (next function) shows the following code:

        next: async (req) => {
          ...
          const fetch = (_a2 = options.fetch) !== null && _a2 !== void 0 ? _a2 : globalThis.fetch;
          const response = await fetch(req.url, Object.assign(Object.assign({}, fetchOptions), { method: req.requestMethod, headers: req.header, signal: req.signal, body }));
          const { isUnaryError, unaryError } = validateResponse(method.methodKind, useBinaryFormat, response.status, response.headers);
          ...
        }

It has a red wavy underline at line const response = await fetch(...).

I'm totally new to react/connect-rpc/react-query, I have read docs of the three and didn't find anything useful to this problem, any help is appreciated, thanks.

@sillykelvin
Copy link
Author

The closest doc I found is error handling of connect-rpc, from the doc, I learned that I need to try-catch the error thrown, but using connect-query/react-query, I have no idea where to catch the error.

@paul-sachs
Copy link
Collaborator

Hi @sillykelvin. Error handling with react-query is a little different compared to vanilla js. Catching errors is really just like you have it, by checking the error field of the return. Combine that with the info you correctly linked to, it could look something like this:

export default function Page() {
  const { isPending, error, data } = useQuery(MyService.method.sayHello, { ... });

  if (error) {
    if (error instanceof ConnectError) {
      return (
        <div>Connect error: {error.message}</div>
      )
    }
    return (
      <div>{error.message}</div>
    );
  }

  if (isPending) {
    return (
      <div>loading data</div>
    );
  }

  return (
    <div>{data}</div>
  );
}

One thing to note about react-query is that it contains default retry logic, so the above will actually only fail after a few retries (see retry option in docs). It sometimes helps to disable retry for all queries when initializing your query client:

import { QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
    },
  },
})

@sillykelvin
Copy link
Author

Really thanks for your kind help, I never realized that it's because the retry option. After retry disabled, errors can be displayed as expected.

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

No branches or pull requests

2 participants