dherault / serverless-offline

Emulate AWS λ and API Gateway locally when developing your Serverless project
MIT License
5.19k stars 795 forks source link

offline: Failure: Query was defined in resolvers, but it's not an object #1081

Closed dnafication closed 2 years ago

dnafication commented 4 years ago

Bug Report

Current Behavior

Using the latest version of serverless-offline (6.7) with apollo-server-lambda is resulting in an error.

offline: ANY /dev (λ: hello)
offline: Failure: Query was defined in resolvers, but it's not an object
Error: Query was defined in resolvers, but it's not an object

Ref: https://github.com/apollographql/apollo-server/issues/4519

Sample Code

service: test

plugins:
  - serverless-offline

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: ap-southeast-2

functions:
  graphql:
    handler: src/graphql.handler
    events:
    - http:
        path: /
        method: any

Basic handler example from apollo server docs

const { ApolloServer, gql } = require('apollo-server-lambda');

// Hardcoded data store
const books = [
  {
    title: 'Harry Potter and the Chamber of Secrets',
    author: 'J.K. Rowling',
  },
  {
    title: 'Jurassic Park',
    author: 'Michael Crichton',
  },
];

// Schema definition
const typeDefs = gql`
  type Book {
    title: String
    author: String
  }

  type Query {
    books: [Book]
  }
`;

// Resolver map
const resolvers = {
  Query: {
    books() {
      return books;
    },
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

exports.handler = server.createHandler();

Expected behavior/code

It used to run perfectly with sls offline start

Environment

optional, if you are using any of the following frameworks to invoke handlers

Possible Solution

Additional context/Screenshots

SRandazzo commented 4 years ago

Thanks for reporting this. I'm new to Serverless and can confirm this occurs using your same Environment config.

Downgrading to 6.6.0 works until there is a proper fix

dejanvasic85 commented 4 years ago

Facing the same issue. But noticed that it actually works on first request. Second request fails with the same error.

offline: [HTTP] server ready: http://localhost:5005 🚀
offline:
offline: Enter "rp" to replay the last request

offline: POST /dev/graphql (λ: graphql)
coming HEREEE
offline: (λ: graphql) RequestId: ckew97vmt0002ptfe3xg55akb  Duration: 292.22 ms  Billed Duration: 300 ms

offline: POST /dev/graphql (λ: graphql)
offline: Failure: Query was defined in resolvers, but it's not an object
Error: Query was defined in resolvers, but it's not an object
gersongams commented 4 years ago

I'm having the same issue 😭

markthethomas commented 4 years ago

When this is resolved would be really curious to see what the issue was - stumped me for a bit! Thought I had a sneaky syntax error lurking or some weird setup 😓 😄

danielholmes commented 4 years ago

I was able to track down a few more details about this error.

The error is raised by the graphql-tools package. Specifically this bit of code runs differently between the first request and subsequent ones:

function getFieldsForType(type) {
    if (type instanceof graphql_1.GraphQLObjectType ||
        type instanceof graphql_1.GraphQLInterfaceType) {
        return type.getFields();
    }
    else {
        return undefined;
    }
}

Adding some logging to the top of this function:

console.log(
    'getFieldsForType',
    type,
    type.constructor,
    type instanceof graphql_1.GraphQLObjectType,
    type instanceof graphql_1.GraphQLInterfaceType
  )

I was able to see this for the first run:

getFieldsForType Query [Function: GraphQLObjectType] true false

And this for subsequent:

getFieldsForType Query [Function: GraphQLObjectType] false false

It reminds be a bit of issues I've had in the past when there's multiple versions of the graphql package in the same project and so instanceof checks would fail when comparing a schema from one of the graphql packages to the types in the other. But I've verified there's definitely only one instance of it in my project.

I'm using serverless-plugin-typescript as well in case it's relevant.

Reverting to 6.6.0 works for me.

shomukai commented 4 years ago

I got a similar issue, allowCache: true solved my problem.

in my severless.yml file:

custom:
  serverless-offline:
    allowCache: true

I think severless-offline reloaded some packages, (but not all) so for the first time, the instanceof is fine, but the second time, the constructor is reloaded and become a new one... That's why the instanceof failed. But haven't trace into severless-offline to find out why.