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

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)

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 17
  • Comments: 52 (14 by maintainers)

Commits related to this issue

Most upvoted comments

any updates here?

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

I am having the same issue in nextjs. three years with the same issue

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

This is still an issue on v2.1.0

the issue still happening, it’s been years.

@david-mcafee have there been any updates to resolve this? The issue has been going on for two years.

Still seeing this with

"aws-appsync": "4.1.9",
"graphql": "15.8.0",

Sorry to bump this again, but I still have this issue with version 3.0.11 I will try to create a reproductible sandbox

Edit: sorry I can’t reproduce with a simple example, as my react app is complex I tried simple sandbox, but issue does not happen In my app, the issue is present with simple subscriptions at the root of the app. They are global subscriptions that updates apollo’s cache data for broadcasting UI updates. But I also have user authorization in parallel (app sync, amplify, cognito etc…)

On our side we have cognito and api key links. Some of our operations are used with cognito others with api key.

// package.json
"@apollo/client": "^v3.4.16",
"@aws-amplify/auth": "^4.3.8",
"@aws-amplify/core": "^4.3.0",
"aws-amplify": "^4.3.4",
"aws-appsync": "^4.1.4",
"aws-appsync-auth-link": "^3.0.7",
"aws-appsync-subscription-link": "^3.0.9"

// start
import { createAuthLink } from 'aws-appsync-auth-link'
import { createSubscriptionHandshakeLink } from 'aws-appsync-subscription-link'

const apiKeyLink = ApolloLink.from([
  errorLink,
  createAuthLink(apiKeyConfig),
  createSubscriptionHandshakeLink(apiKeyConfig),
])

const cognitoLink = ApolloLink.from([
  errorLink,
  createAuthLink(config) as any,
  createSubscriptionHandshakeLink(config),
])

const client = new ApolloClient({
  link: // ... custom conditional link, cognitoLink or apiKeyLink ...,
  cache: new InMemoryCache({
    addTypename: false,
  }),
})

@dexster, @noobling, @joekendal - these fixes are now available on NPM. Can you please upgrade to the latest versions? Thanks, and please let me know if you need further help!

@dexster, @noobling, and @joekendal - we have 2 other fixes that we are currently working on that will go out with our next release. I’ll update this ticket when the change has been pushed to npm. Thanks!

Likewise still seeing this with 3.0.11 and @apollo/client 3.6.6

@adamduren - we just released the latest version of the AppSync SDK on npm, and this fix is included. Please reach out if you have further questions, thanks!

I still have the issue too

"aws-amplify": "^4.3.4",
"aws-appsync": "^4.1.4",
"aws-appsync-subscription-link": "^3.0.9",

I am still seeing this @4.1.4 image

I think you can repro it by switching between React pages multiple times.

@noobling Same, I’ve given up and just gone with polling interval as recommended by the Apollo team. Unfortunately AppSync Subscriptions just aren’t ready for customers as:

  1. There is no way to put it behind CloudFront and have the signature still work using this SDK.
  2. The subscriptionFailedCallback issue is a problem without a fix even in 2021.

It’s a shame that Amazon doesn’t place AppSync SDK as a higher priority as Amplify is not suitable for every project.

@david-mcafee Thanks for the feedback. Here’s a code snippet. As other commenters above have mentioned, subscribeToMore is the culprit. If you comment it out the error goes away. I also noticed that it only happens in Chromium browsers for me. Safari and Firefox don’t show the error

How would the code below look like using apollo client?

import AWSAppSyncClient from 'aws-appsync';

testAppSync() {
        const client = new AWSAppSyncClient({
            url: ...,
            region: ...,
            auth: {
                type: ...,
                credentials: ...
            }
        });

        client.hydrated().then(client => {
            const query = client.watchQuery({
                query: gql(` query List...`),
                fetchPolicy: 'network-only'
            });

            query.subscribe(({data}) => {
                console.log('TEST APPSYNC: ', data);
            });

            query.subscribeToMore<any>({
                document: gql(`subscription OnCreate...`),
                updateQuery: (prev, {
                    subscriptionData: {
                        data: {
                            onCreate: page
                        }
                    }
                }) => {
                   // do something with data
                }
            });
        })
    }

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