Apollo-client: Unable to handle errors in local state management

Created on 13 Mar 2019  路  18Comments  路  Source: apollographql/apollo-client

Intended outcome:

The following @client only query:

const GET_COUNT = gql`
  query GetCount {
    count @client
  }
`;

<Query query={GET_COUNT}>
  {({ loading, error, data }) => {
    if (loading) {
      return <p>Loading GET_COUNT query</p>;
    }
    if (error) {
      return <p>An error ocurred: {error.message}</p>;
    }
    return <p>Page ready</p>
  }}
</Query>

Should be capable of handling an error returned by the resolver:

const resolvers = {
  Query: {
    count() {
      throw new Error('Oh no!')
    }
  }
};

Actual outcome:

The query renders again with error set with the thrown error, but it renders again immediately after with error as undefined, so It's not possible to actually handle the error.

How to reproduce the issue:

I created a repo showing the error, which also shows a error with apollo dev tools: https://github.com/lfades/apollo-state-issue. It's important to notice that I'm not using a GraphQL backend and just using local state management.

Versions

Check the versions in the repo :pray:

Thank you.

Most helpful comment

I'm encountering the same issue. If I understand correctly, the fix would be to add a catch to this promise continuation. Let me know if a PR would be welcome on this; I'd be happy to contribute.

If there were a documented method for writing errors directly to the cache, that could be a feasible short-term workaround.

All 18 comments

All errors thrown in a client side reducer register as network errors. They seem to be cleared when the query is marked as complete. Is there a way to return a GraphQLError from the custom resolver?

Right now trying to figure out this myself too. I can throw errors fine, but the response data shows up as "null" and can't find way to pass the error up back to the query part. I have also tried throwing ApolloError and extends of those (with custom messages).

Also tried onError link for the client.

Case is that the resolvers use outside API to fetch data, but can't figure out way to inform query caller that the API is unavailable (ie. authentication issue).

Thinking about hacking error passing to custom context, not ideal but doable.

I'm seeing the same - in my case I'm attempting to implement a local resolver that passes additional data to a remote graphql query - and if the remote fails, I can't percolate the error back to the caller.

Hey all,

For any production application missing error handling is a total blocker.
With the present behavior it's impossible to use local state management at all.

Is there any update, or a work around for this? Or maybe a pointer on where one would start working on a fix?

Thanks,
Stephan

Edit: For anyone else coming here: Moving back to https://github.com/apollographql/apollo-link-state works.

Adding to the pile: I have a case where the resolver fails at initial page load, but succeeds on subsequent calls of that Query.

The end result is that the data prop remains undefined, even when the resolver is successfully resolving and returning the correct data.

In other words, it seems like once a @client resolver fails once, that query returns undefined from that point on, even if the resolver succeeds.

Anyone else observing this?

We're running into the same issue actually. I may consider moving back to apollo-link-state just to get reasonable error messaging.

Reverting back to apollo-link-state worked for me. The only downside is that Apollo spits out:

Found @client directives in a query but no ApolloClient resolvers were specified. This means ApolloClient local resolver handling has been disabled, and @client directives will be passed through to your link chain.

Apparently it's harmless.

馃し鈥嶁檪

I'm encountering the same issue. If I understand correctly, the fix would be to add a catch to this promise continuation. Let me know if a PR would be welcome on this; I'd be happy to contribute.

If there were a documented method for writing errors directly to the cache, that could be a feasible short-term workaround.

@asselstine Monkey-patch console.warn to ignore this message, if you fancy

  useEffect(() => {
    const _oldConsoleWarn = console.warn;
    console.warn = (...args) => {
      if (args[0]?.constructor === String) {
        const message = args[0];
        for (const prefix of [
          "Found @client directives in a query but no ApolloClient resolvers were specified.",
        ]) {
          if (message.startsWith(prefix)) return;
        }
      }
      _oldConsoleWarn.apply(console, args);
    };
    return () => {
      console.warn = _oldConsoleWarn;
    };
  }, []);

I'm encountering the same issue. If I understand correctly, the fix would be to add a catch to this promise continuation. Let me know if a PR would be welcome on this; I'd be happy to contribute.

If there were a documented method for writing errors directly to the cache, that could be a feasible short-term workaround.

This seems to be the real solution. Thanks

Just ran into this today, this is an absolute requirement for local state management.

I'm encountering the same issue. If I understand correctly, the fix would be to add a catch to this promise continuation. Let me know if a PR would be welcome on this; I'd be happy to contribute.

If there were a documented method for writing errors directly to the cache, that could be a feasible short-term workaround.

I'm encountering the same issue. If I understand correctly, the fix would be to add a catch to this promise continuation. Let me know if a PR would be welcome on this; I'd be happy to contribute.

If there were a documented method for writing errors directly to the cache, that could be a feasible short-term workaround.

Did you push a PR?

Hey everyone, I did some testing with Apollo Client 2.6.8 and it appears to be working now!

What I did:

  1. Create local state resolvers
  2. Throw an error in the resolvers
  3. The component can see the error, i.e. const { data, loading, error } = useQuery(...)

So....all is well now? Perhaps just upgrade everyone!

It does seem to be working - although Apollo-link-error doesn't seem to get called - update callback on hooks doesn't get called - and finally the error is grouped into errors.networkErrors.

Yes, I just noticed. Links are not called for @client queries so there can be no link actions taken on local state queries....what a pain. I'm going to have to downgrade again!

@asselstine Can you please reopen your PR so that this can be fixed properly before v3 comes out of beta?

Hey everyone, I did some testing with Apollo Client 2.6.8 and it appears to be working now!

We're trying to do more or less the same thing in our project, and it seems to be broken in 2.6.8 still, is there an ETA for @asselstine 's PR or another working solution? :)

It seems like everyone has different permutations of this issue.

What I am seeing:

  1. local mutation resolver throws an error
  2. error gets passed to the react component and rendered
  3. immediately after, the error bypasses the error link and the app crashes because of "Unhandled Rejection (Error): Network error: ..."

When performing a query that does a network request (to my graphql server), expected errors are successfully handled by the error link.

I was hoping to use apollo for this new project, but I think I may switch to a simpler tool and revisit when this product is more stable.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jbaxleyiii picture jbaxleyiii  路  43Comments

tomitrescak picture tomitrescak  路  138Comments

paldepind picture paldepind  路  66Comments

stubailo picture stubailo  路  50Comments

joenoon picture joenoon  路  43Comments