Apollo-server: 2.x - Aliases do not work with default resolvers in merged schemas

Created on 25 Sep 2018  Â·  12Comments  Â·  Source: apollographql/apollo-server

I opened an issue on graphql-js: https://github.com/graphql/graphql-js/issues/1530#event-1862105684


Comment by Dan https://github.com/apollographql/apollo-server/issues/1724#issuecomment-425596109

This issues doesn't seem to be related to fragments. Aliases do not appear to be working with default resolvers in merged schemas:


OP:

Basically, when using fragments in a hierarchy like the below query, aliases don't work and can return non-nullable errors or they simply just cause the objects to be null.

It appears that my issue may not be related to the parser itself. This is a bug that was introduced when I upgraded to Apollo Server 2.x. I even rolled back every package _except_ apollo-server to what I had before and the issue persists.

Playground: https://pinto-hip.glitch.me

Issue the query:

{
  books {
    name
    categoryHierarchy {
      ...category
      categories {
        ...category
      }
    }
  }
}

fragment category on Category {
  abc: name
}

Error:

{
  "data": {
    "books": [
      {
        "name": "Harry Potter and the Chamber of Secrets",
        "categoryHierarchy": [
          null
        ]
      },
      {
        "name": "Jurassic Park",
        "categoryHierarchy": [
          null
        ]
      }
    ]
  },
  "errors": [
    {
      "message": "Expected Iterable, but did not find one for field Category.categories.",
      "locations": [
        {
          "line": 6,
          "column": 7
        }
      ],
      "path": [
        "books",
        0,
        "categoryHierarchy",
        0,
        "categories"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Expected Iterable, but did not find one for field Category.categories.",
            "    at invariant (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/jsutils/invariant.js:19:11)",
            "    at completeListValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:673:65)",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:643:12)",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:629:21)",
            "    at completeValueWithLocatedError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:580:21)",
            "    at completeValueCatchingError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:550:12)",
            "    at resolveField (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:497:10)",
            "    at /rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:364:18",
            "    at Array.reduce (<anonymous>)",
            "    at executeFields (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:361:42)"
          ]
        }
      }
    },
    {
      "message": "Expected Iterable, but did not find one for field Category.categories.",
      "locations": [
        {
          "line": 6,
          "column": 7
        }
      ],
      "path": [
        "books",
        1,
        "categoryHierarchy",
        0,
        "categories"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Expected Iterable, but did not find one for field Category.categories.",
            "    at invariant (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/jsutils/invariant.js:19:11)",
            "    at completeListValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:673:65)",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:643:12)",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:629:21)",
            "    at completeValueWithLocatedError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:580:21)",
            "    at completeValueCatchingError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:550:12)",
            "    at resolveField (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:497:10)",
            "    at /rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:364:18",
            "    at Array.reduce (<anonymous>)",
            "    at executeFields (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:361:42)"
          ]
        }
      }
    }
  ]
}
bug has-reproduction

All 12 comments

Do you have an example of some server code that reproduces this?

In the glitch code linked?

On Thu, Sep 27, 2018, 15:40 Dan Crews notifications@github.com wrote:

Do you have an example of some server code that reproduces this?

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/apollographql/apollo-server/issues/1724#issuecomment-425235010,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAiaax3Q6uC7TtYbDCzJXlaVCwY5XM3Kks5ufTfUgaJpZM4W49JV
.

sorry; didn't see a link to the source, and I didn't know glitch's url mechanism. Got it

Expected Iterable, but did not find one for field Category.categories.

The error message is correct Your bug is here:

  const books = [
    {
      name: 'Harry Potter and the Chamber of Secrets',
      author: 'J.K. Rowling',
      categoryHierarchy: [
        { name: 'Fiction', categories: { name: 'Fantasy', categories: [] } }
      ]
    },
    {
      name: 'Jurassic Park',
      author: 'Michael Crichton',
      categoryHierarchy: [
        { name: 'Fiction', categories: { name: 'Sci-Fi', categories: [] } }
      ]
    },
  ];

You aren't returning an Iterable (array) for the first level of categories. Should be:

  const books = [
    {
      name: 'Harry Potter and the Chamber of Secrets',
      author: 'J.K. Rowling',
      categoryHierarchy: [
        { name: 'Fiction', categories: [ { name: 'Fantasy', categories: [] } ] }
      ]
    },
    {
      name: 'Jurassic Park',
      author: 'Michael Crichton',
      categoryHierarchy: [
        { name: 'Fiction', categories: [ { name: 'Sci-Fi', categories: [] } ] }
      ]
    },
  ];

Dang it, I need to try to reproduce it since I'm definitely returning the same structure as I was in apollo-server 1.x in the resolvers, so give me some time to get a proper repro.

One thing I'm doing in my actual app is using mergeSchemas since we keep separate schemas. I'll try to build out the example to see if I can truly reproduce it.

@dncrews OK, I've managed to reproduce it (check the Glitch again)--it definitely seems to be due to my usage of makeExecutableSchema and mergeSchemas. Is there something I'm doing wrong? I thought I was following the docs correctly: https://www.apollographql.com/docs/graphql-tools/schema-stitching.html#adding-resolvers

{
  books {
    books {
      name
      author
      categories {
        ...category
        sub_categories {
          ...category
          sub_categories {
            ...category
          }
        }
      }
    }
  }
}

fragment category on Category {
  id: category_id
  name
}

Response:

{
  "data": {
    "books": {
      "books": [
        {
          "name": "Harry Potter and the Chamber of Secrets",
          "author": "J.K. Rowling",
          "categories": [
            null
          ]
        },
        {
          "name": "Jurassic Park",
          "author": "Michael Crichton",
          "categories": [
            null
          ]
        }
      ]
    }
  },
  "errors": [
    {
      "message": "Cannot return null for non-nullable field Category.category_id.",
      "locations": [
        {
          "line": 20,
          "column": 3
        }
      ],
      "path": [
        "books",
        "books",
        0,
        "categories",
        0,
        "id"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Cannot return null for non-nullable field Category.category_id.",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:631:13)",
            "    at completeValueWithLocatedError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:580:21)",
            "    at completeValueCatchingError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:550:12)",
            "    at resolveField (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:497:10)",
            "    at /rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:364:18",
            "    at Array.reduce (<anonymous>)",
            "    at executeFields (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:361:42)",
            "    at collectAndExecuteSubfields (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:772:10)",
            "    at completeObjectValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:762:10)",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:660:12)"
          ]
        }
      }
    },
    {
      "message": "Cannot return null for non-nullable field Category.category_id.",
      "locations": [
        {
          "line": 20,
          "column": 3
        }
      ],
      "path": [
        "books",
        "books",
        1,
        "categories",
        0,
        "id"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Cannot return null for non-nullable field Category.category_id.",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:631:13)",
            "    at completeValueWithLocatedError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:580:21)",
            "    at completeValueCatchingError (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:550:12)",
            "    at resolveField (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:497:10)",
            "    at /rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:364:18",
            "    at Array.reduce (<anonymous>)",
            "    at executeFields (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:361:42)",
            "    at collectAndExecuteSubfields (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:772:10)",
            "    at completeObjectValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:762:10)",
            "    at completeValue (/rbd/pnpm-volume/0897a123-e913-41b8-a689-0921f96aa33a/node_modules/.registry.npmjs.org/graphql/0.13.2/node_modules/graphql/execution/execute.js:660:12)"
          ]
        }
      }
    }
  ]
}

This issues doesn't seem to be related to fragments. Aliases do not appear to be working with default resolvers in merged schemas:

This doesn't work:

  const typeDefs = gql`
    type Query {
      book: Book
    }

    type Book {
      category: String!
    }
  `;

  const schema = makeExecutableSchema({ typeDefs });

  const resolvers = {
    Query: {
      book: () => ({ category: 'Test' })
    }
  };

  const server = new ApolloServer({
    schema: mergeSchemas({
      schemas: [ schema ],
      resolvers
    }),
  });

This does:

  const typeDefs = gql`
    type Query {
      book: Book
    }

    type Book {
      category: String!
    }
  `;

  const schema = makeExecutableSchema({ typeDefs });

  const resolvers = {
    Query: {
      book: () => ({ category: 'Test' })
    },
    Book: {
      category: (parent) => parent.category // Adding default resolver to fix bug
    }
  };

  const server = new ApolloServer({
    schema: mergeSchemas({
      schemas: [ schema ],
      resolvers
    }),
  });

For now working around using:

import { keyBy, mapValues } from "lodash";

const monkeyPatchForAliases = (...props) =>
  mapValues(
    keyBy(props.map(prop => ({ prop, fn: parent => parent[prop] })), "prop"),
    obj => obj.fn
  );

const resolvers = {
    Query: {
      book: () => ({ category: 'Test' })
    },
    Book: monkeyPatchForAliases("category")
  };

😢

Would be great to get this prioritized, it's definitely a breaking bug and would prevent large projects from migrating.

@kamranayub Are you sure you're using the latest version of apollo-server? I tried to reproduce the issue and it seems to work just fine. Running with node v8.11.3 and this code: gist

I can double check, have you run the glitch code? That is reproducing the
issue live as Dan found.

On Thu, Oct 4, 2018, 12:15 Serge Korzh notifications@github.com wrote:

@kamranayub https://github.com/kamranayub Are you sure you're using the
latest version of apollo-server? I tried to reproduce the issue and it
seems to work just fine. Running with node v8.11.3 and this code: gist
https://gist.github.com/souserge/427d8ef5f9d7f48f120bc52d56917c29

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/apollographql/apollo-server/issues/1724#issuecomment-427099000,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAiaaxAgO1Of6yqWuM2n4Gw2FD9KulLxks5uhkIpgaJpZM4W49JV
.

@souserge With your code and deps it still fails. See:

# Write your query or mutation here
{
  book {
    cat: category
  }
}

And the code: https://glitch.com/edit/#!/pinto-hip

Closing for now, opened in graphql-tools repo.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

espoal picture espoal  Â·  3Comments

jpcbarros picture jpcbarros  Â·  3Comments

nevyn-lookback picture nevyn-lookback  Â·  3Comments

Magneticmagnum picture Magneticmagnum  Â·  3Comments

danilobuerger picture danilobuerger  Â·  3Comments