awslabs / aws-mobile-appsync-sdk-js

JavaScript library files for Offline, Sync, Sigv4. includes support for React Native
Apache License 2.0
919 stars 266 forks source link

Subscription link obfuscates GraphQL errors in onError link #659

Open ShannonLCapper opened 3 years ago

ShannonLCapper commented 3 years ago

Note: If your issue/feature-request/question is regarding the AWS AppSync service, please log it in the official AWS AppSync forum

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

What is the current behavior? When a GraphQL error occurs when trying to connect a subscription (for example, a validation error from an argument being of the incorrect type), the onError link receives a networkError object instead of a graphQLErrors array. The error object returned by the useSubscription hook does return an error, but the GraphQL errors are nested deep within the object as a JSONified string, instead of being available at the top level.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.

import { ApolloClient, ApolloLink, ApolloProvider, useSubscription, gql } from '@apollo/client';
import { InMemoryCache } from '@apollo/client/cache';
import { onError } from '@apollo/client/link/error';
import { AUTH_TYPE, createAuthLink } from 'aws-appsync-auth-link';
import { createSubscriptionHandshakeLink } from 'aws-appsync-subscription-link';

const authLinkOptions: Parameters<typeof createAuthLink>[0] = {
    url: '', // insert real URL here
    region: 'us-west-2',
    auth: {
        type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS,
        jwtToken: '', // insert real JWT here
    },
};

const client = new ApolloClient({
    link: ApolloLink.from([
        onError(({ graphQLErrors, networkError }) => {
            console.log(graphQLErrors); // undefined
            console.log(networkError); // { errors: [{ message: `Connection failed: {"errors":[{"message":"Validation error of type VariableTypeMismatch: Variable type 'Int!' doesn't match expected type 'ID!' @ 'SomeOperationName'"}]}` }]}
        }),
        createAuthLink(authLinkOptions),
        createSubscriptionHandshakeLink(authLinkOptions),
    ]),
    cache: new InMemoryCache(),
});

// Some operation that purposely triggers a validation error, such as by typing
// $myArg as an Int! when the backend expects it to be a String!
const GqlDocument = gql`
    subscription SomeOperationName($myArg: Int!) {
  someSubscription(myArg: $myArg) {
    id
  }
}`;

const MySubscriptionComponent = () => {
    const {
        error, // { errors: [{ message: `Connection failed: {"errors":[{"message":"Validation error of type VariableTypeMismatch: Variable type 'Int!' doesn't match expected type 'ID!' @ 'SomeOperationName'"}]}` }]}
    } = useSubscription(GqlDocument, {
        variables: {
            myArg: 1,
        },
    });

    return null;
}

const App = () => (
    <ApolloProvider client={client}>
        <MySubscriptionComponent />
    </ApolloProvider>
);

What is the expected behavior? I would expect that the GraphQL validation errors would be returned in the GraphQLErrors array in the onError link, not returned as a JSON-ified string concatenated to Connection failed: deep within networkError. It requires some verbose parsing of the networkError object to actually obtain what the GraphQL errors are, and makes it difficult to log unexpected errors separately from expected network connectivity issues.

Which versions and which environment (browser, react-native, nodejs) / OS are affected by this issue? Did this work in previous versions? Browser: Chrome 91.0.4472.164 OS: MacOS 10.15.5 @apollo/client: 3.3.21 aws-appsync-subscription-link: 3.0.7 aws-appsync-auth-link: 3.0.5