graphql-client icon indicating copy to clipboard operation
graphql-client copied to clipboard

unknown variant, there are no variants

Open samuela opened this issue 4 years ago • 4 comments

I have a mutation:

mutation StartThread(
  $commit_hash: String!
  $file_path: String!
  $line_number: Int!
  $body: String!
  $author_github_node_id: String!
) {
  # Make sure that we have an entry in the `lines` table to attach our thread to.
  insert_lines_one(
    object: {
      commit: $commit_hash
      file_path: $file_path
      line_number: $line_number
    }
    on_conflict: {
      constraint: lines_pkey
      # TODO: This is a hack. This is the only way to do an upsert in hasura; we must update at least one field.
      update_columns: [commit, file_path, line_number]
    }
  ) {
    __typename
  }

  # Now we can insert our thread.
  insert_threads_one(
    object: {
      original_commit: $commit_hash
      original_file_path: $file_path
      original_line_number: $line_number
      comments: {
        data: [{ author_github_node_id: $author_github_node_id, body: $body }]
      }
    }
  ) {
    id
    comments {
      id
    }
  }
}

The details aren't super important except for the fact that there are two separate clauses in the mutation. graphql_client will accept this and compile just fine but it fails parsing the response at runtime:

error decoding response body: unknown variant `lines`, there are no variants at line 1 column 49

How does one set up a mutation with multiple clauses when using graphql_client?

samuela avatar Oct 25 '21 03:10 samuela

Update: seems like the issue is not that the multiple clauses bit but rather that receiving a response like {"data":{"insert_lines_one":{"__typename":"lines"}}} make graphql_client very unhappy. I have the following code:

let response_body = response.text().await?;
log::trace!("hasura response: {}", response_body);
let response_parsed: graphql_client::Response<T> = serde_json::from_str(&response_body)?;

which outputs:

[2021-10-25T04:54:12Z TRACE api::hasura] hasura response: {"data":{"insert_lines_one":{"__typename":"lines"}}}
[2021-10-25T04:54:12Z ERROR api] calling hasura::start_thread
    
    Caused by:
...
        2: unknown variant `lines`, there are no variants at line 1 column 49

samuela avatar Oct 25 '21 05:10 samuela

Hi this happened to me as well. Minimal reproduce is here.

https://github.com/graphql-rust/graphql-client/compare/main...ulwlu:test_multiple_implement?expand=1

@samuela did you find some workaround? I've seen that sometimes

https://github.com/graphql-rust/graphql-client/blob/main/graphql_client_codegen/src/codegen/enums.rs#L78-L87

this part goes wrong when there is a data like {"data": {burabura.....}} same as you.

ghost avatar Mar 31 '22 00:03 ghost

@ulwlu I don't remember 100% off the top of my head by I think I added a field to my query that I didn't really need and that just made it magically go away...

samuela avatar Mar 31 '22 00:03 samuela

i believe this is caused at calculate_selection

Query { fragments: [], operations: [ResolvedOperation { name: "BadQuery", _operation_type: Query, selection_set: [SelectionId(0)], object_id: ObjectId(0) }], selection_parent_idx: {SelectionId(3): InlineFragment(SelectionId(2)), SelectionId(0): Operation(OperationId(0)), SelectionId(1): Field(SelectionId(0)), SelectionId(2): Field(SelectionId(0))}, selections: [Field(SelectedField { alias: None, field_id: StoredFieldId(1), selection_set: [SelectionId(1), SelectionId(2)] }), Typename, InlineFragment(InlineFragment { type_id: Object(ObjectId(2)), selection_set: [SelectionId(3)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(3), selection_set: [] })], variables: [] }, 2
Object(ObjectId(2)), None

Query { fragments: [ResolvedFragment { name: "NamesFragment", on: Union(UnionId(0)), selection_set: [SelectionId(9), SelectionId(10), SelectionId(12), SelectionId(14)] }], operations: [ResolvedOperation { name: "UnionQuery", _operation_type: Query, selection_set: [SelectionId(0)], object_id: ObjectId(3) }, ResolvedOperation { name: "FragmentOnUnion", _operation_type: Query, selection_set: [SelectionId(16)], object_id: ObjectId(3) }, ResolvedOperation { name: "FragmentAndMoreOnUnion", _operation_type: Query, selection_set: [SelectionId(18)], object_id: ObjectId(3) }], selection_parent_idx: {SelectionId(6): InlineFragment(SelectionId(4)), SelectionId(7): Field(SelectionId(0)), SelectionId(11): InlineFragment(SelectionId(10)), SelectionId(15): InlineFragment(SelectionId(14)), SelectionId(16): Operation(OperationId(1)), SelectionId(18): Operation(OperationId(2)), SelectionId(19): Field(SelectionId(18)), SelectionId(17): Field(SelectionId(16)), SelectionId(20): Field(SelectionId(18)), SelectionId(21): InlineFragment(SelectionId(20)), SelectionId(0): Operation(OperationId(0)), SelectionId(12): Fragment(ResolvedFragmentId(0)), SelectionId(4): Field(SelectionId(0)), SelectionId(5): InlineFragment(SelectionId(4)), SelectionId(14): Fragment(ResolvedFragmentId(0)), SelectionId(9): Fragment(ResolvedFragmentId(0)), SelectionId(10): Fragment(ResolvedFragmentId(0)), SelectionId(1): Field(SelectionId(0)), SelectionId(2): Field(SelectionId(0)), SelectionId(13): InlineFragment(SelectionId(12)), SelectionId(8): InlineFragment(SelectionId(7)), SelectionId(3): InlineFragment(SelectionId(2))}, selections: [Field(SelectedField { alias: None, field_id: StoredFieldId(7), selection_set: [SelectionId(1), SelectionId(2), SelectionId(4), SelectionId(7)] }), Typename, InlineFragment(InlineFragment { type_id: Object(ObjectId(2)), selection_set: [SelectionId(3)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(5), selection_set: [] }), InlineFragment(InlineFragment { type_id: Object(ObjectId(0)), selection_set: [SelectionId(5), SelectionId(6)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(0), selection_set: [] }), Field(SelectedField { alias: None, field_id: StoredFieldId(1), selection_set: [] }), InlineFragment(InlineFragment { type_id: Object(ObjectId(1)), selection_set: [SelectionId(8)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(3), selection_set: [] }), Typename, InlineFragment(InlineFragment { type_id: Object(ObjectId(2)), selection_set: [SelectionId(11)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(5), selection_set: [] }), InlineFragment(InlineFragment { type_id: Object(ObjectId(0)), selection_set: [SelectionId(13)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(0), selection_set: [] }), InlineFragment(InlineFragment { type_id: Object(ObjectId(1)), selection_set: [SelectionId(15)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(3), selection_set: [] }), Field(SelectedField { alias: None, field_id: StoredFieldId(7), selection_set: [SelectionId(17)] }), FragmentSpread(ResolvedFragmentId(0)), Field(SelectedField { alias: None, field_id: StoredFieldId(7), selection_set: [SelectionId(19), SelectionId(20)] }), FragmentSpread(ResolvedFragmentId(0)), InlineFragment(InlineFragment { type_id: Object(ObjectId(2)), selection_set: [SelectionId(21)] }), Field(SelectedField { alias: None, field_id: StoredFieldId(6), selection_set: [] })], variables: [] }, 4
Union(UnionId(0)), Some([Object(ObjectId(0)), Object(ObjectId(2)), Object(ObjectId(1))])
"Person"
"Dog"
"Organization"
"Person"

upper one failed to get variables, so it won't be added to enum of serde_tag"typename".

so, workaround is add below.

union TEMP = ***(what you'll use ... on)

this makes it work. now i'm thinking why author avoids object but allow only interface and union.

ghost avatar Apr 02 '22 18:04 ghost