简体   繁体   中英

GraphQL Error Handling with ApolloClient and Apollo-Server-Express

The onError function from apollo-link-error has a populated graphQLErrors Object, but when ApolloClient throws an error object, the graphQLErrors property contains an empty array. Further inspection reveals the graphql error message in error.networkError.result.errors .

How can one properly configure Apollo Client to return a populated graphQLErrors object?

Apollo Client Setup:

const {ApolloClient} = require('apollo-client')
const { ApolloLink } = require('apollo-link')

const {HttpLink} = require('apollo-link-http')
const {onError} = require('apollo-link-error')
const {InMemoryCache} = require('apollo-cache-inmemory')

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
      ),
    )
  }

  if (networkError) console.log(`[Network error]: ${networkError}`)
})

const middleware = (req, ignored_res, next) => {
  const client = new ApolloClient({
    link: ApolloLink.from([errorLink, new HttpLink({ uri:'http://somegraphqlserver.com', fetch: require('node-fetch') })]),
    cache: new InMemoryCache(),
  })

  req.GQLClient = client

  return next()
}

module.exports = middleware

Calling apollo-server-express:

req.GQLClient
    .query({
      query: SOME_MALFORMED_QUERY,
    })
    .then((data) => {...})
    .catch((error) => {
      console.log('rawError', error)
      console.log('error.networkError.result.errors', error.networkError.result.errors)
      return next(error)
    })

Console Results:

[GraphQL error]: Message: Cannot query field "blah" on type "CustomerList"., Location: [object Object], Path: undefined
[Network error]: Error: Response not successful: Received status code 400


 rawError { Error: Network error: Response not successful: Received status code 400
   at new ApolloError (/.../node_modules/apollo-client/bundle.umd.js:121:28)
   at /.../node_modules/apollo-client/bundle.umd.js:1187:41
   at /.../node_modules/apollo-client/bundle.umd.js:1620:17
   at Array.forEach (<anonymous>)
   at /.../node_modules/apollo-client/bundle.umd.js:1619:18
   at Map.forEach (<anonymous>)
   at QueryManager.broadcastQueries (/.../node_modules/apollo-client/bundle.umd.js:1614:22)
   at /.../node_modules/apollo-client/bundle.umd.js:1114:31
   at process._tickCallback (internal/process/next_tick.js:178:7)
 graphQLErrors: [],
 networkError: 
  { Error: Response not successful: Received status code 400
   at throwServerError (/.../node_modules/apollo-link-http-common/lib/bundle.umd.js:33:21)
   at /.../node_modules/apollo-link-http-common/lib/bundle.umd.js:58:17
   at process._tickCallback (internal/process/next_tick.js:178:7)
    response: 
     Response {
       size: 0,
       timeout: 0,
       [Symbol(Body internals)]: [Object],
       [Symbol(Response internals)]: [Object] },
    statusCode: 400,
    result: { errors: [Array] } },
 message: 'Network error: Response not successful: Received status code 400',
 extraInfo: undefined }


error.networkError.result.errors [ { message: 'Cannot query field "blah" on type "CustomerList".',
   locations: [ [Object] ] } ]

library versions:

Server:

"apollo-server-express": "^1.3.2"

Client:

"apollo-cache-inmemory": "^1.1.12"
"apollo-client": "^2.2.8"
"apollo-link-error": "^1.0.9"
"apollo-link-http": "^1.5.4"

This is by design. From the docs :

  • graphQLErrors: An array of errors from the GraphQL endpoint
  • networkError: Any error during the link execution or server response, that wasn't delivered as part of the errors field in the GraphQL result

In other words, if your query is malformed, you request a field that isn't valid (like in your example), or hit any other issue that results in status other than 200, the error will appear as part of the networkError property. On the other hand, if the request returns a 200, but the errors array inside the response is populated, those same errors will be returned as part of graphQLErrors .

If you want to see an example of graphQLErrors being populated, format your query correctly but have one of your resolvers throw an error as soon as it's called. As long as the query doesn't hit any other issues, you should see the same error pop up inside graphQLErrors .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM