0
votes

I am using Apollo Server and Apollo Client and am having trouble handling unauthenticated responses. On the server, I throw AuthenticationError when a request is made and the user is not authenticated. On the client side, executing a query/mutation when unauthenticated sends an error to the catch block where I can see a graphQLErrors with "code":"UNAUTHENTICATED", exactly as expected.

What I would like to do is handle all of these unauthenticated responses in one central location so that if any request, ever, returns as unauthenticated I can redirect the user to the login page. The documentation for apollo-link-error shows how to use onError as an error handler with an example about unauthenticated responses.

The code I wrote in onError says if there are graphQLErrors that have the code "UNAUTHENTICATED", set "response.errors" to "undefined" and redirect to the login page. This logic seemingly works as expected as any unauthenticated requests are redirected to the login page.

However, the addition of response.errors = undefined as indicated in the "Ignoring errors" section of the apollo-link-error documents results in all unauthenticated requests throwing a Error writing result to store for query error. If I remove the response.errors = undefined logic, then the graphQLErrors "code":"UNAUTHENTICATED" error ends up in the catch block of every unauthenticated query/mutation which means I would need logic in every catch block to ignore that error but show others.

Am I doing something wrong here? How can I use onErrors to trap all "unauthenticated" errors and prevent them from appearing in the query/mutation catch blocks without the error listed above?

1
Can you show your implementation? Do you use two onError functions or did you merge them together?Gh05d
Only one onError. I eventually worked through the issue and have posted and answer about what was happening.justinvoelker

1 Answers

0
votes

This answer helped me break down the problem and with enough troubleshooting I was able to arrive at the following answer for my particular situation.

By setting "response.errors" to undefined, request promises were resolved instead of rejected and the data being read in the "then" block did not exist which resulted in the error.

I'm writing the longer answer below from recollection as I have completely changed all of this logic in my application and no longer use any part of this process. I just wanted to provide an answer to anyone else having a similar issue.

My goal was to check all responses for authentication errors and redirect to the login page if necessary or otherwise continue as planned. Ideally, I would remove the authentication error from the response so that I could still handle other GraphQL errors at the query/mutation. Maybe it's my inexperience with Apollo (or JS in general), but I just could not get that to work.

Here's what I found. When using the onError method of apollo-link-error, you intercept all responses with errors and can perform whatever logic you desire (e.g. redirect if unauthenticated). However, this doesn't end the process. The calling query/mutation is still going to receive this response and the error may still need to be addressed. For example, if you have a catch statement that displays a notification to the user, an error handled in the onError method will still exist in the response. One way around this is to add response.errors = undefined to the onError method. Doing so will clear the unauthenticated error (and any other errors) from the response and continue.

This is where I was getting hung up. By clearing the errors from the response, the query/mutation promise will resolve instead of reject. Because it resolves, any logic inside the "then" block is executed which means the data that attempts to be parsed from a successful response is now attempting to be parsed from an error response. Sure, the "then" block could have been updated to check for data but in my view that defeats the purpose of the promise in the first place.

It was at this point that I decided to write a custom error handler and eliminate the use of onError. I found it easier to handle everything myself than try to delegate a portion to apollo-link-error but still have to handle some error handling logic elsewhere.