Aws-mobile-appsync-sdk-js: Exception when unmounting before subscription websocket connection fully initialized

Created on 17 Jan 2020  路  13Comments  路  Source: awslabs/aws-mobile-appsync-sdk-js

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

The following exception is thrown when a graphql()-enhanced React component is unmounted before the subscription websocket connection is fully initialized:

TypeError: Cannot read property 'subscriptionFailedCallback' of undefined

    at AppSyncRealTimeSubscriptionHandshakeLink.<anonymous> (*******/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js:307:112)
    at step (*******/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js:56:23)
    at Object.next (*******/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js:37:53)
    at fulfilled (*******/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js:28:58)
    at process._tickCallback (internal/process/next_tick.js:68:7)

This issue is mentioned in the code base: https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/139a9775eebe6ac8a9df0b72975b522eeb2867cf/packages/aws-appsync-subscription-link/src/realtime-subscription-handshake-link.ts#L299-L301

We are currently working around it using the following patch:

diff --git a/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js b/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js
index 6eb828e..03ee7e5 100644
--- a/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js
+++ b/node_modules/aws-appsync-subscription-link/lib/realtime-subscription-handshake-link.js
@@ -304,7 +304,12 @@ var AppSyncRealTimeSubscriptionHandshakeLink = /** @class */ (function (_super)
                         }
                         return [2 /*return*/];
                     case 5:
-                        _g = this.subscriptionObserverMap.get(subscriptionId), subscriptionFailedCallback = _g.subscriptionFailedCallback, subscriptionReadyCallback = _g.subscriptionReadyCallback;
+                        try {
+                            _g = this.subscriptionObserverMap.get(subscriptionId), subscriptionFailedCallback = _g.subscriptionFailedCallback, subscriptionReadyCallback = _g.subscriptionReadyCallback;
+                        } catch (e) {
+                            return [2 /*return*/];
+                        }
+
                         // This must be done before sending the message in order to be listening immediately
                         this.subscriptionObserverMap.set(subscriptionId, {
                             observer: observer,

What is the expected behavior?

Don't throw exception if unmounting before websocket connection is fully initialized.

Which versions and which environment (browser, react-native, nodejs) / OS are affected by this issue? Did this work in previous versions?

aws-appsync-subscription-link v2.0.1 with aws-appsync-react 3.0.2
Browser and nodejs (in tests)

to-be-reproduced subscription-link

Most helpful comment

Any updates on this? this is also affecting aws-amplify version 3.3.7

All 13 comments

This is still an issue on v2.1.0

any updates here?

Hi, I am also encountering this issue but this time after I logout in the app. Any work arounds?
Screen Shot 2020-08-07 at 1 14 04 pm

Cheers

Any updates on this? this is also affecting aws-amplify version 3.3.7

Still an issue. Fix should be trivial and simple (at least a try/catch).

I, too, am having this issue.

Still having this issue after #616 is merged.

Found a workaround:
https://github.com/awslabs/aws-mobile-appsync-sdk-js/issues/491#issuecomment-671469907

I, too, am having this issue.

+1

My Sentry is filled with this issue

+1

+1, would love to not have to see this hit in Sentry all the time

Found a workaround:
#491 (comment)

The solution there did not work some of the time, and is not very elegant. I found that this error was less likely to occur once I switched to subscribeToMore instead of useSubscription. This way it waits for the component to mount before establishing the WebSocket connection.

Additionally this suggestion for wrapping subscribeToMore in useLayoutEffect as opposed to useEffect will fire after all DOM mutations.

const { data, error, loading, subscribeToMore } = useQuery(gql(getPosts))


useLayoutEffect(() => {

    subscribeToMore({
        document: gql(onNewPost),

        variables: { user_id: user?.id },

        updateQuery: (prev: Post[], { subscriptionData }) => {
            if(subscriptionData.data) return prev;
            const newPost: Post = subscriptionData.data.onNewPost
            return Object.assign({}, prev, [newPost])
        }
    })

}, [subscribeToMore])
Was this page helpful?
0 / 5 - 0 ratings

Related issues

JonathanHolvey picture JonathanHolvey  路  4Comments

asadowns picture asadowns  路  3Comments

mwarger picture mwarger  路  3Comments

kabriel picture kabriel  路  4Comments

wzup picture wzup  路  3Comments