Search code examples
sentry

Plugin errors after upgrading appolo-server-express from v2 to v3


I'm using the plugin example from one of Sentry's help pages. It was working fine - but after upgrading to apollo-server-express 3 I'm getting the following typescript error. I don't understand what I have to do in order to fix the error.

TS2322: Type '{ requestDidStart(: any): { didEncounterErrors(ctx: any): void; }; }[]' is not assignable to type 'PluginDefinition[]'.   Type '{ requestDidStart(: any): { didEncounterErrors(ctx: any): void; }; }' is not assignable to type 'PluginDefinition'.     Type '{ requestDidStart(_: any): { didEncounterErrors(ctx: any): void; }; }' is not assignable to type 'ApolloServerPlugin<Record<string, any>>'.       The types returned by 'requestDidStart(...)' are incompatible between these types.         Type '{ didEncounterErrors(ctx: any): void; }' is missing the following properties from type 'Promise<void | GraphQLRequestListener<Record<string, any>>>': then, catch, [Symbol.toStringTag], finally types.d.ts(45, 5): The expected type comes from property 'plugins' which is declared here on type 'Config'

Here's the plugin:

const plugins = [
    {
       requestDidStart(_:any) {
        /* Within this returned object, define functions that respond
           to request-specific lifecycle events. */
        return {
          didEncounterErrors(ctx:any ) {
            // If we couldn't parse the operation, don't
            // do anything here
            if (!ctx.operation) {
              return
            }

            for (const err of ctx.errors) {
              // Only report internal server errors,
              // all errors extending ApolloError should be user-facing
              if (err instanceof ApolloError) {
                continue;
              }

              // Add scoped report details and send to Sentry
              Sentry.withScope(scope => {
                // Annotate whether failing operation was query/mutation/subscription
                scope.setTag("kind", ctx.operation.operation);

                // Log query and variables as extras (make sure to strip out sensitive data!)
                scope.setExtra("query", ctx.request.query);
                scope.setExtra("variables", ctx.request.variables);

                if (err.path) {
                  // We can also add the path as breadcrumb
                  scope.addBreadcrumb({
                    category: "query-path",
                    message: err.path.join(" > "),
                    level: Sentry.Severity.Debug
                  });
                }

                const transactionId = ctx.request.http.headers.get(
                  "x-transaction-id"
                );
                if (transactionId) {
                  scope.setTransaction(transactionId);
                }

                Sentry.captureException(err);
              });
            }
          }
        };
      }
    }
  ]

Solution

  • Add the async keyword before requestDidStart and before didEncounterErrors

    Looks like the expected return result has to be a Promise now.