3
votes

What I'm you doing?:

I would like to thrown an error on apollo-server and process it on client.

Note: I'm using apollo-link-error middleware on apollo-client.

Server:

import { UserInputError } from "apollo-server";

 Mutation: {     
    someMutation : { 
     try {
       // here is some code which failed
      } catch (error) { 
// base Error class has message property by default 
// response just hold some additional informations 
       throw new UserInputError(error.message, { response });
      }
    }
  }

Client:

simplified implementation of my mutation on client

    <Mutation
       mutation={CREATE_ORDER}
     >
        {(createOrder, { loading, error }) => (
        ....
         try {
           await createOrder({  variables: {...}});
         } catch (createOrderError) {
          //  here I get Cannot read property 'data' of undefined
            console.log(createOrderError);

          }

         )}
   </Mutation>

I receive following error on client (in catch clause in the code above):

TypeError: Cannot read property 'data' of undefined
    at Mutation._this.onMutationCompleted (react-apollo.browser.umd.js:631)
    at react-apollo.browser.umd.js:586

This error looks like problem with httpLink.

Response: (from network tab in chrome dev tools)

enter image description here

From graphql spec :

If an error was encountered during the execution that prevented a valid response, the data entry in the response should be null.

So I assume that my response from server is valid. The data object should be null.

What do I expect to happen?:

I would like to access to response from apollo server How could I achieve this?

Thanks for help!

1

1 Answers

2
votes

Things to check before accessing the data returned from query or mutation

  1. If loading -> return some loader component
  2. If error is present -> display some error component

If not any of above two conditions matched then for sure you have the data.

Apart from that you need to have

1.On Apollo Client "errorPolicy"

 const client = new ApolloClient({
    defaultOptions: {
      watchQuery: {
        errorPolicy: 'all'
      },
      query: {
        errorPolicy: 'all'
      },
      mutate: {
        errorPolicy: 'all'
      }
    },
    link,
    cache,
    connectToDevTools: true,
  })

2.For customising error sent from server -

You can use formatError

const server = new ApolloServer({
  ...root,
  resolverValidationOptions: {
    requireResolversForResolveType: false,
  },
  formatError, <---------- send custom error
  formatResponse: (response, query) => formatResponse({ response, query }),
  dataSources,
  context: async ({ req, res }) => {
    const user = req.user;
    return { user, req, res };
  }
});

e.g

const formatError = (error) => {
  const { extensions } = error;
  logger.error(error);

  const exception = extensions.exception ? extensions.exception : {};
  logger.error('\nStackTrace');
  logger.error(exception.stacktrace);
  exception.stacktrace = null;
  const extractedError = extractErrorFromExtention(extensions);

  return extractedError || { message: error.message, code: extensions.code, exception };
};