Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't find field on ROOT_QUERY object error on 3.4.x and up #8593

Closed
hueter opened this issue Aug 5, 2021 · 9 comments · Fixed by #8604
Closed

Can't find field on ROOT_QUERY object error on 3.4.x and up #8593

hueter opened this issue Aug 5, 2021 · 9 comments · Fixed by #8604
Assignees

Comments

@hueter
Copy link

hueter commented Aug 5, 2021

Hello,

After upgrading to 3.4.x, I have had problems with certain queries being reissued with different variables resulting in an Apollo error that crashes my app.

Intended outcome:

useQuery can be re-executed multiple times with different variables and not crash.

Actual outcome:

This crash happens:

error

Following the traceback, I placed a debugger in ObservableQuery at getCurrentResult:

Screen Shot 2021-08-05 at 3 11 44 PM

Note that the network request worked and the backend resolved the query successfully:

Screen Shot 2021-08-05 at 3 15 02 PM

How to reproduce the issue:

I am having a lot of difficulty reproducing the error in the sandbox, but here's a bunch of things that I tried / additional information:

  • The affected queries have deeply-nested arguments, where subsequent queries change things that are deeply nested, e.g.
{
 "limit": 25,
 "offset": 0,
 "filters": [ /* deeply nested objects w/arrays. This is what changes between queries */ ]
}
  • This error still happens when I do fetchPolicy: 'network-only' and nextFetchPolicy: 'network-only'
  • Still happens when I call refetch with new variables or the same query with new variables
  • I also tried doing skip: true and only using refetch and it still happened
  • Also tried this setting on the apollo client instance after reading the CHANGELOG and it did not resolve the issue:
new ApolloClient({
  defaultOptions: {
    watchQuery: {
      refetchWritePolicy: "merge",
    },
  },
})

Versions

I reproduced this error on the following:

  • 3.4.0
  • 3.4.1
  • 3.4.5
  • 3.5.0-beta.4

However downgrading to 3.3.21 fixed the issues.

Additional Notes

I'm wondering if this could possibly be related to #8422 because it touched the file where I'm getting the error.

Please let me know if there's anything to try or if any additional info would be helpful.

@benjamn
Copy link
Member

benjamn commented Aug 5, 2021

@hueter I believe this may be a consequence of #8262, which came before #8422 (though that's a reasonable suspect too). The motivation for #8262 was to avoid situations where both result.data and result.error are undefined, by providing a result.error with information about missing cache fields. That behavior is new in v3.4, so we're definitely still open to feedback on how it works in practice.

Can you tell where the error is actually logged/thrown? The stack trace attached to the error shows where the ApolloError object was created, but it would also be useful to know where/why result.error got logged/thrown (and whether it happened in application/component code or inside @apollo/client).

@hueter
Copy link
Author

hueter commented Aug 5, 2021

hi @benjamn thanks for the reply and context. For context, yes we usually throw errors that come from apollo queries and catch them with parent error boundary components like so:

Screen Shot 2021-08-05 at 5 26 07 PM

@benjamn
Copy link
Member

benjamn commented Aug 5, 2021

On a different note, I'm also curious to figure out why the field was missing in the first place. Do you see any keys starting with contactsCollection in the __APOLLO_CLIENT__.cache.data.data.ROOT_QUERY object, around the time the error is logged?

@hueter
Copy link
Author

hueter commented Aug 5, 2021

Yep, before the error, during the debugger statement (while the error is being initialized), and after the error is thrown, I had two keys:

Screen Shot 2021-08-05 at 5 50 36 PM

@benjamn
Copy link
Member

benjamn commented Aug 5, 2021

In case this is useful, you can control the serialization of the contactsCollection field arguments using a keyArgs field policy:

new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        contactsCollection: {
          // Use keyArgs to configure args serialization:
          keyArgs: ["params", ["order"]], // Serialize only args.params.order, not limit or offset
          keyArgs: false, // Disables the serialization, so the key is just contactsCollection
        },
      },
    },
  },
})

However, I should also mention these MissingFieldErrors are meant to be information and not fatal. If we're causing more problems than we're solving by providing result.error when a cache read is incomplete, that's an argument for not reporting result.error for these errors.

@hueter
Copy link
Author

hueter commented Aug 5, 2021

Ah interesting, thank you for the insight! I guess it's a tough call from the API design perspective, but as an end user I was expecting result.error to be present only if it were fatal -- although I know some folks might expect partial failures with GraphQL, so I'm not sure if I should change my assumption to always throw if the error is present. Would this be related to the error policy settings, i.e. is there an error policy that lets me ignore non-backend / network errors?

I also just tested the code and setting the query's fetchPolicy to no-cache fixed the issue. Previously I only tested it with network-only, but I see now according to the docs that network-only still writes to the cache after the network request is complete.

I'll have to read up on the caching serialization to see if that could provide an alternative as well.

Thanks for the follow-up! This has been helpful.

@benjamn benjamn self-assigned this Aug 6, 2021
@brainkim
Copy link
Contributor

brainkim commented Aug 6, 2021

Related: #8442

I’m also seeing transitory Missing Cache Field errors on the error property in unit tests while refactoring code. A potential option might be to make these console warnings only.

@benjamn
Copy link
Member

benjamn commented Aug 6, 2021

@brainkim I've got an idea for a PR to handle this, coming shortly!

benjamn added a commit that referenced this issue Aug 6, 2021
Should fix #8593, which suggests including `MissingFieldError`s in
`result.error` was more disruptive than helpful.
@benjamn
Copy link
Member

benjamn commented Aug 6, 2021

@hueter @brainkim Please take a look at #8604 when you have a chance!

benjamn added a commit that referenced this issue Aug 6, 2021
Should fix #8593, which suggests including `MissingFieldError`s in
`result.error` was more disruptive than helpful.
benjamn added a commit that referenced this issue Aug 9, 2021
Should fix #8593, which suggests including `MissingFieldError`s in
`result.error` was more disruptive than helpful.
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
3 participants