Graphql-tools: mergeSchemas doesn't allow built in scalars in secondary schemas

Created on 30 May 2018  路  15Comments  路  Source: ardatan/graphql-tools


I have the following code:

return mergeSchemas({
    schemas: [actions, typeDefs],
    resolvers,
    schemaDirectives: {
      date: DateFormatDirective,
    },
  });

actions is a schema made using makeRemoteExecutableSchema and typeDefs is a big gql schema string. The actions schema does not contain any use of the built in Float, but typeDefs does.

When you query the actions schema directly:

{
  __type(name:"Float") {
    name
  }
}

you get back

{
  "data": {
    "__type": null
  }
}

rather than

{
  "data": {
    "__type": {
      "name": "Float"
    }
  }
}

This is normal and expected.

However, when the above mergeSchemas function is called, an error is thrown:

     Error: Can't find type Float.
      at /usr/src/app/node_modules/graphql-tools/src/stitching/mergeSchemas.ts:102:13
      at resolveType (node_modules/graphql-tools/src/stitching/schemaRecreation.ts:187:14)
      at /usr/src/app/node_modules/graphql-tools/src/stitching/schemaRecreation.ts:156:18
      at Array.forEach (<anonymous>)
      at fieldMapToFieldConfigMap (node_modules/graphql-tools/src/stitching/schemaRecreation.ts:154:23)
      at fields (node_modules/graphql-tools/src/stitching/schemaRecreation.ts:48:9)
      at resolveThunk (node_modules/graphql/type/definition.js:370:40)
      at defineFieldMap (node_modules/graphql/type/definition.js:532:18)
      at GraphQLObjectType.getFields (node_modules/graphql/type/definition.js:506:44)
      at typeMapReducer (node_modules/graphql/type/schema.js:232:38)
      at typeMapReducer (node_modules/graphql/type/schema.js:213:12)
      at typeMapReducer (node_modules/graphql/type/schema.js:213:12)
      at typeMapReducer (node_modules/graphql/type/schema.js:213:12)
      at /usr/src/app/node_modules/graphql/type/schema.js:239:20
      at Array.forEach (<anonymous>)
      at typeMapReducer (node_modules/graphql/type/schema.js:232:51)
      at /usr/src/app/node_modules/graphql/type/schema.js:239:20
      at Array.forEach (<anonymous>)
      at typeMapReducer (node_modules/graphql/type/schema.js:232:51)
      at Array.reduce (<anonymous>)
      at new GraphQLSchema (node_modules/graphql/type/schema.js:122:28)
      at mergeSchemasImplementation (node_modules/graphql-tools/src/stitching/mergeSchemas.ts:243:22)
      at mergeSchemas (node_modules/graphql-tools/src/stitching/mergeSchemas.ts:75:10)
      ...

It seems like the built in scalar types have to be used in the first schema for them to be valid in any subsequent schemas passed to mergeSchemas.

I'm guessing this isn't intentional functionality :smile:

Most helpful comment

Found a "quick n dirty" work around that does the job until fixed. Simply apply a "mock" schema as the 1st element in the array of schemas to be merged.

    // apply a default schema before merging - work around for a bug in mergeSchemas
    const abc = makeExecutableSchema({
      typeDefs: `
      type Query         
      type Mutation
      type Subscription
      type Mock {
          a: Int
          b: Float
          c: String
          d: Boolean
          e: ID
      }
      `,
    });

    return mergeSchemas({
      resolvers,
      schemas: [abc, myRealSchema],
    });

Adding the reference to the types seemed to suppress any issues with GraphQLScalarType being undefined.

There may be a nicer way of doing this (tidyer mocked schema etc), but wanted to post the general jist to help out any stranded devs! :)

All 15 comments

I also face similar issue.
Luckily, I can get gql definition for every types.
So I consolidate all gql(s) and combine it then makeExecutableSchema only once.
Do you happen to workaround the issue now ?

any update on this? I'm able to reproduce this.

I'm having the same issue, although in mine, none of the base types is used in the first schema. The first schema only declares new scalar types. The one GraphQL complains about in the second schema is Float.

Inserting the text:

scalar Float
scalar Int

...in the second schema was enough to get it working.

Here is a minimal reproduction of the issue:

import { mergeSchemas } from 'graphql-tools';

const BookSchema = `
  type Book {
    name: String
  }
`;

mergeSchemas({ schemas: [BookSchema] });

Using makeExecutableSchema will get around this issue. I think the root issue has something to do with the way mergeSchemas parses the schema. Fields of scalar types end up being represented by GraphQLObjectType rather than GraphQLScalarType

@hayes you are right, using makeExecutableSchema does fix it

Instead of doing

const mergedSchema = mergeSchemas({
    schemas: [RemoteSchema, LocalSchema],
  });

I'm doing

const mergedSchema = mergeSchemas({
    schemas: [RemoteSchema, makeExecutableSchema({ typeDefs: LocalSchema })],
    resolvers,
  });

Note: For this to work, the resolvers have to be part of the mergeSchemas, they can't be part of the ApolloServer props. One issue with this is with the typings, the resolvers params in mergeSchemas expects a IResolversParameter when the ApolloServer expects an IResolvers . Not sure what's the difference tho

The problem seems to be fixed in graphql-tools version 5.0.0-rc.0 :tada: .

I hope we can have a stable version soon :smiley:

Yes 5.0.0-rc.0 works fine 馃憤

Can confirm 5.0.0-rc.0 fixes this, but I'm getting the following issue now:

TypeError: Cannot read property 'getType' of undefined

See my issue here: #1095

Found a "quick n dirty" work around that does the job until fixed. Simply apply a "mock" schema as the 1st element in the array of schemas to be merged.

    // apply a default schema before merging - work around for a bug in mergeSchemas
    const abc = makeExecutableSchema({
      typeDefs: `
      type Query         
      type Mutation
      type Subscription
      type Mock {
          a: Int
          b: Float
          c: String
          d: Boolean
          e: ID
      }
      `,
    });

    return mergeSchemas({
      resolvers,
      schemas: [abc, myRealSchema],
    });

Adding the reference to the types seemed to suppress any issues with GraphQLScalarType being undefined.

There may be a nicer way of doing this (tidyer mocked schema etc), but wanted to post the general jist to help out any stranded devs! :)

I am using Hasura and ID type was not working, @JoshKneale workaround solved the issue, but it definitely should not be the definitive solution.

Also having this issue with apollo-server-lambda.

Also having this issue with apollo-server-lambda.

update to 5.0.0-rc.0. It solved the issue for me.

Closing as fixed in master, try graphql-tools@next for additional fixes

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adamkl picture adamkl  路  3Comments

benjaminhon picture benjaminhon  路  3Comments

dcworldwide picture dcworldwide  路  4Comments

sebas5384 picture sebas5384  路  4Comments

stubailo picture stubailo  路  3Comments