apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

exception in suspense query: Cannot read properties of undefined (reading 'errors')

Open andreimatei opened this issue 1 year ago • 16 comments

Issue Description

I sometimes see the following error, which I believe indicates a bug in the apollo library. I should mention that I think this happens when my component gets into an infinite rerender loop (so I'm probably screwing something up), but it looks to me like Apollo has a problem nonetheless; the error is seen after a handful of render iteration in this loop.

Cannot read properties of undefined (reading 'errors')
    at toApolloError (useSuspenseQuery.ts:321:33)
    at useSuspenseQuery.ts:227:19
    at updateMemo (react-dom.development.js:17246:19)
    at Object.useMemo (react-dom.development.js:17886:16)
    at Object.useMemo (react.development.js:1650:21)
    at useSuspenseQuery (useSuspenseQuery.ts:226:28)
    at Login (login.tsx:143:25)
    at renderWithHooks (react-dom.development.js:16305:18)
    at updateFunctionComponent (react-dom.development.js:19588:20)
    at beginWork (react-dom.development.js:21601:16)

Link to Reproduction

N/A

Reproduction Steps

No response

@apollo/client version

3.9.5

andreimatei avatar Mar 12 '24 21:03 andreimatei

Hey @andreimatei 👋

Thanks for reporting! A reproduction would be super helpful if you can provide one. The stack trace points to this area of code but without a reproduction its a bit difficult to understand how it gets into this state. Any more information you can provide would be super helpful. Thanks!

jerelmiller avatar Mar 12 '24 21:03 jerelmiller

I am facing the same error after v3.8.8 with any unhandled graphql error:

ApolloError: xxx
    at new ApolloError2 (chunk-7EYSJOP3.js?v=a8c04c3c:154:28)
    at toApolloError (@apollo_client.js?v=a8c04c3c:1497:43)
    at @apollo_client.js?v=a8c04c3c:1465:14
    at mountMemo (chunk-QYYA6GZJ.js?v=a8c04c3c:12817:27)
    at Object.useMemo (chunk-QYYA6GZJ.js?v=a8c04c3c:13141:24)
    at Object.useMemo (chunk-64YSJXBX.js?v=a8c04c3c:1094:29)
    at _useSuspenseQuery (@apollo_client.js?v=a8c04c3c:1461:18)
    at useSuspenseQuery (@apollo_client.js?v=a8c04c3c:1394:129)

~~seems like something here introduced it~~ (no it's not, it's 3.9.0+) https://github.com/apollographql/apollo-client/releases/tag/v3.8.9

tarasmatsyk avatar Apr 22 '24 16:04 tarasmatsyk

@tarasmatsyk do you have a reproduction we can use? We have extensive tests against errors in useSuspenseQuery already, but without a reproduction, its difficult to understand what is causing this.

jerelmiller avatar Apr 22 '24 16:04 jerelmiller

@jerelmiller not yet, just went through 3.8.9 and 3.8.10 and they seem to be working fine, but not 3.9.0

tarasmatsyk avatar Apr 22 '24 16:04 tarasmatsyk

Good to know! Though I admit I'm a tad confused since that contradicts your original statement. Did you mean to link to the 3.9.0 release in your message? I'm not sure I'm understanding where 3.8.9 comes into play here.

jerelmiller avatar Apr 22 '24 16:04 jerelmiller

@jerelmiller yeah, my bad

I get the same error as topic starter if I use apollo v3.9.0 and above, everything before works fine. The main difference from my tests is that before useSuspenseQuery was throwing an error if gql request gets unhandled error, and now it returns {data: null, error: ApolloError}, or in other words it* behaves in the same way useQuery does

ignore 3.8.9, I am using 3.8.8. 3.8.9 and 3.8.10 work* in the same way, the issue starts from 3.9.0. 3.89 was my initial assumption before I conducted* more tests

tarasmatsyk avatar Apr 22 '24 16:04 tarasmatsyk

Ok thanks for confirming that! Like I said, a reproduction would be super helpful to understand what is going on. To my knowledge, nothing changed with error handling between the two versions, but clearly something is going on. Alternatively, if you're able to, a Replay would help as well. If you go that route, feel free to email me the reproduction if you don't feel comfortable sharing the public URL to jerel.miller[at]apollographql.com

jerelmiller avatar Apr 22 '24 17:04 jerelmiller

unfortunately, this is all I have so far,

I don't understand why one suspense throws an error to handle by upper components in case of gql failure and another returns an error and an empty result, not even having a clue where to look for a hint. The absence of loading attribute is the only difference between suspense and original query hooks.

I'll add more details if I figure out what causes the difference.

PS. In any case, I appreciate the effort, and thanks for the package, guys!

tarasmatsyk avatar Apr 22 '24 18:04 tarasmatsyk

@tarasmatsyk the only time that should happen is if you change the errorPolicy from none (the default) to all. Setting it to all allows you to use partial data from responses that contain errors, so we don't throw in those cases. See error handling in our docs for more info on this.

Do you perhaps have errorPolicy set in either the hook options or defaultOptions in the ApolloClient constructor?

jerelmiller avatar Apr 22 '24 18:04 jerelmiller

@jerelmiller That was my guess from the very beginning, but I use defaults (none if I read sources/docs correctly)

tarasmatsyk avatar Apr 22 '24 18:04 tarasmatsyk

this link says

By default, both network errors and GraphQL errors are thrown by useSuspenseQuery. These errors are caught and displayed by the closest [error boundary](https://react.dev/reference/react/Component#static-getderivedstatefromerror).

this is exactly what I need and use with 3.8.8, but error boundary and suspense query don't work anymore after upgrade

tarasmatsyk avatar Apr 22 '24 18:04 tarasmatsyk

Hmmmm the mystery continues. I've not seen that happen before without setting errorPolicy to something different. We have a full test suite against this that remained passing with the minor version, so perhaps there is something else going on here?

That being said, I think this might actually be a different issue than originally reported here. Would you mind opening a separate issue for this so we can track it separately? I'll tag it as "needs reproduction" until you're able to provide one for us. Until then, there isn't much we can do 🙁

jerelmiller avatar Apr 22 '24 18:04 jerelmiller

I am pretty sure it's the same issue, this is the error I get if I unpack useSuspenseQuery response

  const {data, error, networkStatus} = useSuspenseQuery<MyType>(Query, {
   variables: myVariables},
   errorPolicy: "none", // just for testing purposes, didn't change anything
 });
// data = null, error = "posted a few lines below", networkStatus: 8

an error (v3.9.0)

ApolloError: "error message coming from API"
    at new ApolloError2 (index.ts:101:10)
    at toApolloError (useSuspenseQuery.ts:322:7)
    at useSuspenseQuery.ts:275:14
    at mountMemo (react-dom.development.js:17225:19)
    at Object.useMemo (react-dom.development.js:17670:16)
    at Object.useMemo (react.development.js:1650:21)
    at useSuspenseQuery (useSuspenseQuery.ts:269:16)
    at CustomComponent
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20074:13)

perhaps react-dom is involved somehow, I have a limited understanding of what happens here and cannot reproduce the issue if I pass my GQL response into unit tests apollo-client has (or I am bad at it)

the server response is pretty trivial

{
   "data": null,
   "errors": [
       {
           "message": "error message coming from API",
           "locations": [
               {
                   "line": 2,
                   "column": 3
               }
           ], // no idea where this comes from
           "path": [
               "items"
           ],
           "extensions": {
               "code": 4,
               "exception": null
           }
       }
   ]
}

maybe someone else stumbles across this thread and can add more meaningful details .

PS. Let's keep this thread until we get more details, I want to spend a few more hours on this later this week. I really don't want to abandon suspense or migrate to another package

tarasmatsyk avatar Apr 22 '24 18:04 tarasmatsyk

@tarasmatsyk the original issue states:

Cannot read properties of undefined (reading 'errors')

I think that comes from this line: https://github.com/apollographql/apollo-client/blob/765a94d5d7e70d3fb6d65a15d97339b56afaf205/src/react/hooks/useSuspenseQuery.ts#L337-L339

which tells me result is somehow undefined. Reading your issue, it looks like the error is from GraphQL itself, not a runtime error in the library, so this made me think yours is a separate issue.

jerelmiller avatar Apr 22 '24 18:04 jerelmiller

@tarasmatsyk I'm not advocating we get rid of this thread, just that we are now discussing two different bugs in the same thread and that gets a bit difficult for us to track. I'd prefer if we can continue discussion on the original issue (cannot read properties of undefined) in this thread.

Moving what you're seeing to a separate issue means we can provide as much detail on your issue without convoluting the two together. It also means that if we solve one issue but not the other, we can safely close out the issue without making it look like both are solved. Does that make sense?

jerelmiller avatar Apr 22 '24 19:04 jerelmiller

@jerelmiller you are right, I was confused by the error, but those 2 look different

I've filed an issue here: https://github.com/apollographql/apollo-client/issues/11800

feel free to delete the thread if it helps

tarasmatsyk avatar Apr 22 '24 19:04 tarasmatsyk

We're closing this issue now but feel free to ping the maintainers or open a new issue if you still need support. Thank you!

github-actions[bot] avatar Jun 14 '24 05:06 github-actions[bot]

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. For general questions, we recommend using StackOverflow or our discord server.

github-actions[bot] avatar Jul 16 '24 00:07 github-actions[bot]