graphql-code-generator: `yarn graphql-codegen` returns `Error: Query root type must be provided.` when query root is named other than `Query`.

Describe the bug yarn graphql-codegen returns Error: Query root type must be provided. when query root is named other than Query, for example query_root as in Hasura.

To Reproduce

Steps to reproduce the behavior: run this CodeSandbox, or clone this repo and yarn install && yarn graphql-codegen.

The operation succeeds if query_root is renamed Query, or if @graphql-codegen/cli is downgraded to 1.15.0 or below.

The operation fails if @graphql-codegen/cli version is set to 1.15.1 or any superior version. (Tested 1.15.1, 1.15.4, 1.17.10, 1.21.3).

  1. My GraphQL schema:
type query_root {
    user(id: ID!): User!
}

type User {
    id: ID!
    username: String!
    email: String!
}
  1. My GraphQL operations:
query user {
    user(id: 1) {
        id
        username
        email
    }
}
  1. My codegen.yml config file:
schema: schema.graphql
documents: document.graphql
generates:
  types.ts:
    plugins:
      - typescript
      - typescript-operations

Expected behavior: this should succeed I think?

Environment:

  • OS: Ubuntu 20.10
  • @graphql-codegen/...: anything >= 1.15.1
  • NodeJS: 12

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 7
  • Comments: 52 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@lilred I think you’re hitting a very similar issue to ours. Your issue here was very helpful, our repositories now work again when reverting back and freezing the cli to 1.15.0.

I suspect, like you did too, that somewhere after 1.15.0 they stopped reading the schema {} SchemaDefinition in the schemas. What package / dependency exactly causes this I don’t know, if someone has any pointers to where it should check for SchemaDefinition, we can try to solve this.

This shouldn’t have happened and has caused many people a lot of wasted time, it’s a breaking change and should have been defined as a breaking change in someone’s package according to the widely used semantic versioning.

The issue here seems to be with schemas like the following:

schema {
    query: query_root
}

type Query {
    one: String
}

type query_root {
    two: String
}

graphql-js will parse this fine, however the AST generated somewhere in seemingly graphql-tools outputs something that is then handed to graphql-js, which will happily overwrite query_root with Query.

Hasura is also what I’ve been using, and only once I started adding a Remote Schema did it actually break.

If you control the schema of the remote schema you are adding, you can modify it not to use Query, and instead define it similar to Hasura like so:

  type query_root {
    file_user(user_id: Int!, file_id: String!): String
    file_group(group_id: Int!, file_id: String!): String
  }

  schema {
    query: query_root
  }

such that it won’t be eaten by graphql-tools.

This of course is a non-preferable workaround sadly.

Fixed in https://github.com/dotansimha/graphql-code-generator/pull/6622 ! Thanks everyone to help us to reproduce and fix the issue.

The issue here seems to be with schemas like the following: @jackharrhy

Ah interesting Mine was also Hasura with a remote schema

Banged my head against the wall with this issue as well for a few hours 🙁

Downgrading graphql-codegen/cli from 1.21.2to 1.15.0 worked for me!

@ItsWendell when I add the schema {} declaration to my minimal repro above it works. I think the bug is only present on more complex schemas, such as those produced by Hasura in real-world usage. If you can manage to produce a repro that still features the schema {} declaration I’m sure that could be helpful to the implementers. (I could perhaps do this myself but again I’ve run out of time I can commit to this for now.)

@AradAral Thanks! I’ll take a look and see if I can find anything.

I spent about an hour dealing with this, and fixed it by updating graphql from 14 to 15. not sure what else could have been involved but here are my other packages after I got it working:

I assume it’s possible one of these packages had an incompatibility with graphql@14, but in my case it was just easier to start from a clean slate with yarn graphql-codegen init and incrementally move that clean slate back into my project.

As @ferm10n suggested, upgrading to graphql v15+ fixed it for me too. Check your lock file to make sure you’ve actually updated to that version and you don’t have something else depending on v14 holding you back.

Add SchemaDefinition 😃

schema {
  query: query_root
}

You’re using the plugin typescript-operations. It requires(obviously) knowing which ObjectTypeDefinition is the query type. By convention, this is Query by default. However, your case is not, thus you should explicitly specify it.

@dimbslmh I need a failing test like I said multiple times above 😃 https://github.com/ardatan/graphql-tools/pull/3489 Please see here it passes, I can try to fix it if you help me to reproduce it in GraphQL-Tools repo.

@msimon I see what the issue is and I am trying to debug the issue and it seems like GraphQL Tools doesn’t overwrite schema definition like said above. I couldn’t figure out what causes that. And the test cases I added to GraphQL Tools seems working fine. You can see I added more but it still works fine https://github.com/ardatan/graphql-tools/pull/3092/files#diff-311682076d0958c6482f2bdaa569e6f84db27ef175d6145a6805e4bf11e237c1R1397

For anyone using Hasura with remote schema, the comment for @jackharrhy does work well. (https://github.com/dotansimha/graphql-code-generator/issues/5758#issuecomment-835699251)

The goal is to remove the Type Query, Type Mutation & Type Subscription from the final schema that we get from hasura.

Since hasura merge the remote schema and its own, defining the remote server schema with same type name as hasura fixes the issue.

In NestJs, this is a bit hard to do, as the type are hardcoded. First you must rename the Resolver enum from NestJs Graphq:

import { Resolver as ResolverEnum } from '@nestjs/graphql/dist/enums/resolver.enum.js'
//@ts-ignore
ResolverEnum.QUERY = "query_root"
//@ts-ignore
ResolverEnum.MUTATION = "mutation_root"
//@ts-ignore
ResolverEnum.SUBSCRIPTION = "subscription_root"

This must executed before any @Query/@Mutation for the name to be taken into account.

Then modify the schema with the transformSchema & transformAutoSchemaFile:

    GraphQLModule.forRoot({
      ....
      transformAutoSchemaFile: true,
      transformSchema: (schema) => {
        const schemaConfig = schema.toConfig()
        const query = schemaConfig.query
        if (query) {
          query.name = "query_root"
        }
        const mutation = schemaConfig.mutation
        if (mutation) {
          mutation.name = "mutation_root"
        }
        const subscription = schemaConfig.subscription
        if (subscription) {
          subscription.name = "subscription_root"
        }
        return new GraphQLSchema(schemaConfig)
      }
    }),

This is a temporary hack of course. It may break when updating nestJs.

@ardatan I create a very small repo with the error described in this ticket: https://github.com/msimon/codegen_hasura_remote_schema_bug

As @jackharrhy precised, the issues happens when Type Query/Type Mutation/Type Subscription is present but the schema is defined as:

schema {
    query: query_root
    mutation: mutation_root,
    subscription: subscription_root.
}

For the error to happen, the reference must be called in one of the document.

E.g: schema.graphql

schema {
    query: query_root
}

type Query {
    one: String
}

type query_root {
    two: String
}

This would have no problem to generate.

But defining a document that reference two will generate the error:

codegen_bug/src/graphql.d.ts:

query getTwo {
  two
}

I’ll try to do a PR for failing test, but that will not be coming until end of next week at best.

@jackharrhy my repro only has one top-level query type, doesn’t that contradict your hypothesis?

graphql-codegen does some post processing on the schemas it’s handed so it’s best to see what the schema that’s failing to validate actually is vs. the schema you are handing to graphql-codegen

I did this by using printSchema from the graphql-js package just before the validation error was thrown and I saw the invalid schema that didn’t match the schema that was passed in

Hi everyone and thank you for the reports

Sorry but I’m not adding a lot here but just labeling it according to our new Contribution Guide and issue flow.

It seems already got into stage 1 thanks to your reproduction! Thank you for that!

Now in order to advance to stage 2 we’ll need a failing test, would be great if someone could help progress the issues through the stages.

Thank you and sorry that this comment is not a complete solution (yet).