facebook / relay

Relay is a JavaScript framework for building data-driven React applications.
https://relay.dev
MIT License
18.41k stars 1.83k forks source link

Variable "$id_0" of type "ID" used in position expecting type "ID!" error when refetching. #839

Closed F21 closed 8 years ago

F21 commented 8 years ago

Relay generates queries like this when fetching:

query Overview_ResourcesRelayQL($id_0:ID){
  node(id:$id_0){
    id,__typename,
    ...F0
  }
} 

fragment F0 on Faction{
  id,
  name
}

The type for ID should be ID! rather than ID, otherwise we get this error:

Variable "$id_0" of type "ID" used in position expecting type "ID!"
josephsavona commented 8 years ago

Thanks for reporting this. Is this a query that you wrote directly (i.e. in a route), or is this a query that Relay generated (i.e. from a setVariables call)? If the latter, how was the node originally fetched, and what was the type of its id field?

F21 commented 8 years ago

That query is generated by relay.

This is the original query (generated using routes and fragments by relay):

{
   "query":"query App{resources{id,...F0}} fragment F0 on Resources{memory{total,used,when,id},cpu{total,used,when,id},disk{total,used,when,id},id}",
   "variables":{

   }
}

I then use this.props.relay.forceRefetch(...) to force relay to poll the server for an update, which results in this query being generated:

{
   "query":"query Overview($id_0:ID){node(id:$id_0){id,__typename,...F0}} fragment F0 on Resources{memory{total,used,when,id},cpu{total,used,when,id},disk{total,used,when,id},id}",
   "variables":{
      "id_0":"cmVzb3VyY2VzOnJlc291cmNlcw=="
   }
}

The type (I am using the golang version of graphql + relay) is a string.

albertstill commented 8 years ago

Had the exact same problem today at my company for Innovation Day. Relay was generating the query when I called setVariables to increase the count of a first argument in a connection field. The original query that worked fine and was using a custom non-node ID as it's argument property(id: "XY-12341-GA") that returned the Property type which implements the Node interface. The subsequent query used the node field with it's GUID. I used the graphql-relay helper functions and it's a graphql-js server.

Hack I did to get it to work for demo day tomoz was to remove the non null wrapping on the ID argument of node:

nodeField.args.id.type = GraphQLID;

And here is the query that errored:

query Properties_PropertyIDRelayQL($id_0: ID, $category_1: PropertyIDCategoryEnum!) {
  node(id: $id_0) {
    ...F1
  }
}

fragment F0 on PropertyID {
  bedrooms
  bathrooms
  id
}

fragment F1 on PropertyID {
  _similarListings442kDu: similarListings(category: $category_1, after: "YXJyYXljb25uZWN0aW9uOjQ=", first: 5) {
    edges {
      node {
        id
        ...F0
      }
      cursor
    }
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
  }
  id
}

Adding a ! to the end of $id_0: ID in GraphiQL meant the query worked.

Side note: Loving GraphQL and Relay the more I use it, keep up the good work!

josephsavona commented 8 years ago

@F21 @albertstill thanks for the extra information, I see what's going on. This is an inadvertent side-effect of d55b04ebb11a105f7f63eb8a2ce82b782be22d78, which explicitly set all query metadata including the node field's argument type. The printer sees this type and prints it as-is - i'll change the type to ID!.

josephsavona commented 8 years ago

This is fixed and master and will go out in the next release. Thanks everyone for the examples and repro steps!