Apollo-client: Print better error when type definitions are present in documents on the client

Created on 12 Sep 2016  路  12Comments  路  Source: apollographql/apollo-client

I was trying to list users in my app and I encountered with a strange behaviour when I was trying to implement the filtering feature to my users query.

I'm using React-Router and below in the code, I'm getting URL query and pass it to users query. It works as expected at first with any query. But when I run -let's say- browserHistory.push('users?username=test') to push a new state and change the query, apollo client sends the query again but also UsersFilterInput (which I believe it should not send)

Here's my wrapper;

const QUERY = gql`
  query Users($query: UsersFilterInput) {
    users(query: $query) {
      id
      username
      nickname
      level
      avatar
      createdAt
    }
  }

  input UsersFilterInput {
    page: Int
    orderBy: String
    orderDir: String
    username: String
    nickname: String
    level: String
  }
`;

@graphql(QUERY, {
  options({ location: { query } }) {
    return {
      variables: {
        query,
      },
    };
  },
})

Here's the working first query that sent to server;
{"query":"query Users($query: UsersFilterInput) {\n users(query: $query) {\n id\n username\n nickname\n level\n avatar\n createdAt\n }\n}\n","variables":{"query":{"page":"0"}},"operationName":"Users"}

Here's the broken second query that sent to server;
{"query":"query Users($query: UsersFilterInput) {\n users(query: $query) {\n id\n username\n nickname\n level\n avatar\n createdAt\n }\n}\n\ninput UsersFilterInput {\n page: Int\n orderBy: String\n orderDir: String\n username: String\n nickname: String\n level: String\n}\n","variables":{"query":{"username":"ad"}},"operationName":"Users"}

And the error message from server
{"errors":[{"message":"GraphQL cannot execute a request containing a InputObjectTypeDefinition.","locations":[{"line":12,"column":1}]}]}

Most helpful comment

No, you can just use the input type:

const QUERY = gql`
  query Users($query: UsersFilterInput) {
    users(query: $query) {
      id
      username
      nickname
      level
      avatar
      createdAt
    }
  }
`;

Since the server already knows about the input type, you don't need to do anything extra.

All 12 comments

I don't think your query is valid GraphQL syntax. The input type definition needs to go into the server's schema, you can't add input types on the client.

We didn't foresee the situation, so there isn't a good error message for this.

What was your intention when including the input type definition in the query?

I already defined the same input definition at server side. I am new to graphql so I thought I needed to send an input object with the same structure from client. That's why I tried to create a definition at client and attach it to query.

Edit: Also since the first query that sent is working as expected, I thought that was actually valid.

Yeah, I think we should have a better error there. You only need to define the input type on the server.

Just to be clear, do i have to pass each variable individually to that query? Like;

query Users($page: Int, $username: String){
    users(query: { page: $page, username: $username }) {

Or is there any other solution you can point me?

No, you can just use the input type:

const QUERY = gql`
  query Users($query: UsersFilterInput) {
    users(query: $query) {
      id
      username
      nickname
      level
      avatar
      createdAt
    }
  }
`;

Since the server already knows about the input type, you don't need to do anything extra.

That's great. It's working like a charm now, thank you.

Yeah an easy way to test this stuff out is to put it in GraphiQL instead. If it works in GraphiQL, it will work in Apollo Client.

Want to submit a PR to add a better message? It should be easy to just add an if statement here: https://github.com/apollostack/apollo-client/blob/e14c50dc8362c72d4bda51684f2269d86c71bb00/src/queries/getFromAST.ts#L42

I think you could check for anything that's not an OperationDefinition or FragmentDefinition, and say something like "Schema type definitions not allowed in queries."

Sorry to open this again, but is there a way to do this without reusing server schema? Working on the case with separate client and API.

The following illustrates what I'm trying to do, but getting syntax error.

const updateProfile = gql`
  type Profile {
    firstName: String!
    lastName: String!
    position: String!
  }

  mutation updateProfile($_id: String!, $profile: Profile) {
    updateProfile(_id: $_id, profile: $profile) {
      _id
    }
  }
`;

this works for me thanks

Sorry to open this again, but is there a way to do this without reusing server schema? Working on the case with separate client and API.

The following illustrates what I'm trying to do, but getting syntax error.

const updateProfile = gql`
  type Profile {
    firstName: String!
    lastName: String!
    position: String!
  }

  mutation updateProfile($_id: String!, $profile: Profile) {
    updateProfile(_id: $_id, profile: $profile) {
      _id
    }
  }
`;

Any solutions for this? Also running into same trouble.

@PendicGordan - you can define a client schema, check the docs

Was this page helpful?
0 / 5 - 0 ratings