apollo-client: Unhandled Rejection (Error): GraphQL error: Authentication required

Hi there,

I’ve been trying to implement authentication to a project of mine using apollo-client and apollo-server. It is really simple:

  1. on app load I fetch the user’s info from a me query
  2. if the user isn’t logged in, the server throws an AuthenticationError
  3. after login, I refetch the user’s info from the me query, to update the client’s cache
  4. on logout, I clear the cache using client.resetStore
  5. because of that, my app rerenders and tries to get the user’s info from the me query again
  6. the user isn’t logged in, the server throws an AuthenticationError
  7. but this time a see huge error screen in my React application

Looking at the dev tools, everything looks fine.

At page load, the user is not logged in. The me query returns null (and an AuthenticationError error) image

After login, I get data from the me query image

Finally, after logout, the me query returns again null (and an AuthenticationError error) image

But this time my client app breaks with this error image

I find this a bit weird because the cache at page load and after logout is the same (empty cache). And the server responses are identical, yet the client behaves differently.

My implementation is pretty similar to the one described in the official documentation (using cookies).

Does anybody have an idea why this happens?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 29
  • Comments: 44 (5 by maintainers)

Commits related to this issue

Most upvoted comments

This temporarily helps me avoid the pain of using try, catch block.

const [login, { data, loading, error }] = useLoginMutation({ onError: () => {} });

I hope to see the solution to this problem soon. Thanks for your hard work, Apollo team!

not sure if this helps but i had a similar issue where throwing a AuthenticationError from Apollo-Server was causing my Apollo-Client react error page to appear due to an unhandled rejection. In my case, I wrapped my mutation in a try catch block and awaited the mutation response and it seemed to work.

IE This leads to an unhandled rejection error:

  const onSubmit = (e: React.ChangeEvent<HTMLFormElement>) => {
    e.preventDefault();
    login({ variables: { input: loginFormState } });
  };

This works and allows me to grab the error from the mutation to display on the UI

  const onSubmit = async (e: React.ChangeEvent<HTMLFormElement>) => {
    e.preventDefault();
    try {
      await login({ variables: { input: loginFormState } });
    } catch (e) {
      console.error(e);
    }
  };

Dealing with this for 2 hours wondering why my app constantly was crashing.

Nothing about this in the official documentation, and no response from the maintainers.

@josuevalrob if you’re trying to use the onError callback I think you actually need to implement it as prop on your Mutation component itself rather than on the apolloClient instantiation alone.

ie:

<Mutation mutation={requestAccess} onCompleted={handleComplete} **onError={handleError}**>
        { (graphQlCallback, { loading, error }) => (
                <>
                <Form onSubmit={ e => handleInvitation(e, graphQlCallback) ...>
                {/* here the error destructured variable from the callback is filled with the error data */}
                {error && <p>Error :( {error.message}</p>}
                {error && console.error(error)} {/* you can see the error object here. */}
                </>
        )}
</Mutation>

You should then be able to use your handleInvitation function as you had it before:

const handleInvitation = (event, graphQlCallback) => {
  event.preventDefault();
  graphQlCallback({variables: {input:formState.values}})
};

If you do this you shouldn’t need to catch the error from the call to the mutate function if you’re not fan of that.

Alternatively if you don’t want to use the onError prop on the Mutation component to specify the onError callback, you can use an alternative syntax to the try/catch scenario to something like:

const handleInvitation = (event, graphQlCallback) => {
  event.preventDefault();
  graphQlCallback({variables: {input:formState.values}}).catch(err => doSomethingWithError(err))
};

Hopefully one of these approaches works for your needs

Can we get a little more information about the resolution here? Merely saying it’s fixed doesn’t actually solve the larger problem here. When we get unhandled errors we turn to issues such as this to find out why and what we can do to potentially fix the issue.

Not everyone can be on the bleeding edge of the client. Also @latest also doesn’t help future people coming in as latest can be different from when it was published.

Is there a PR that we can reference that addresses this issue? Is there any background that we can use for us who can’t yet update our package version on a whim?

If you are using the useMutation hook the following works:

const [login, { loading, error }] = useMutation<
    LoginMutation,
    LoginMutationVariables
  >(LOGIN, {
    onCompleted({ login }) {
      console.log("register :>> ", login, loading, error);
    },
    onError(error) {
      console.error("error :>>", error.message);
    },
  });

Hey guys! I had exactly the same problem. And solution was simple:

  • just change ‘client.resetStore()’ to ‘client.clearStore()’. That’s it! No refetching will be performed 😃 Happy coding!

I have a big application that sometimes does try to catch and sometimes it is just using the generic onError functionality we have created.

Easiest fix for us was to update the apolloClient configuration with defaultOptions like this:

export default new ApolloClient({
  link,
  cache,
  defaultOptions: {
    mutate: { errorPolicy: 'ignore' },
  },
});

But the problem with this is that now the promises always resolve successfully, so the places that are using the .then on the promise are always called even when the mutation is failing.

This should no longer be an issue in @apollo/client@latest - let us know otherwise, thanks!

Just adding a callback on onError property worked for me.

eg.

<Mutation variables={state} onError={onError} mutation={CREATE_NEW_USER}>

I have traced this down, at least in @apollo/react-hooks@3.15 which which ships with apollo-boost@0.4.7 to this block of code:

https://github.com/apollographql/react-apollo/blob/4bd40a94b18102b1eb42864d2e59d52ced0303f5/packages/hooks/src/data/MutationData.ts#L81-L89

The errorPolicy is never destructured from the options, and subsequently never passed to the underlying client mutation call.

Can someone jump in explain whether this error handling behavior is a bug or by design? The same behavior happened in Apollo Client 2 (https://github.com/apollographql/apollo-client/issues/3876), and since this hasn’t been fixed yet, is this by design? If it is by design, it should be noted that the error handling behavior is inconsistent between useQuery and useMutation.

I have same issue … and look like Apollo team don’t care about fixing this!

@lfrallon Reading through this thread, I fear that these are a lot of very different problems that just piled up in this issue - some people report it is fixed, others don’t.
I fear at this point it might get confusing to have a deeper in-depth discussion in this issue.

Could you please open a new issue for your case, and please include a reproduction? The issue template should point you to a few “reproduction starters”, so you don’t have to create one from scratch.

same issue. setting errorPolicy to all not works!