zino-hofmann / graphql-flutter

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.
https://zino-hofmann.github.io/graphql-flutter
MIT License
3.25k stars 623 forks source link

Subscription Error #1191

Closed Arpit1496 closed 1 year ago

Arpit1496 commented 2 years ago

When using useSubscription with codegen, the widget displays "Bad state: stream has already been listened to." error.

budde377 commented 2 years ago

Thanks for reporting. Can you please provide an example of how you're using it and the error

Arpit1496 commented 2 years ago

I am using the generated useSubscription call simply by passing options. The widget extends the HooksWidget and return a Text of subscribed object (id). The subscription used for generating works fine in Altair. Websocket cloent is used with auth link.concat to provide authorization and bearer token.

The Client: ` final httpLink = HttpLink(HTTP_END_POINT); final websocketLink = WebSocketLink(WS_END_POINT);

final authLink = AuthLink( getToken: () async => 'Bearer ${(await AuthService.to.getToken())?.accessToken ?? ''}', );

final link = authLink.concat(Link.split( (request) => request.isSubscription, websocketLink, httpLink, ));

return GraphQLClient( link: link, cache: GraphQLCache(), defaultPolicies: DefaultPolicies( query: Policies( fetch: FetchPolicy.networkOnly, )));`

What is expected is that even if the client is wrong, the stream should not show bad state error. Instead show that error in result.exception.

Arpit1496 commented 2 years ago

On further debugging by using Channel generator in websocketlink, I was able to print this "flutter: QueryResult(source: QueryResultSource.network, data: null, context: Context({}), exception: OperationException(linkException: UnknownException({type: error, id: cc4dcd66-9e94-4fab-929a-055e04c3277e, payload: {message: input:22: Subscription "LiveStatusSubscription" must select only one top level field. }}, stack:), graphqlErrors: []), timestamp: 2022-08-01 01:01:45.371823)"

Again to say, my subscription works perfectly fine in Altair. May be an issue with init_connection ? How can I check that initial payload contains my headers of auth for init_connection ?

budde377 commented 2 years ago

Your issue seem to be because you're selecting multiple top level fields. Check if you're adding __typename (probably implicitly).

I agree it shouldn't show a state error.

Arpit1496 commented 2 years ago

Thanks for the immediate response. Saved a lot of time. You were absolutely right.It was the problem of __typename field in auto generated query.

For future readers: if using codegen library, add this in build.yaml in options section. " addTypenameExcludedPaths:

Also the Client would return null values in list (may be from cache) if you remove __typename from query/mutations altogether.

Arpit1496 commented 2 years ago

Your issue seem to be because you're selecting multiple top level fields. Check if you're adding __typename (probably implicitly).

I agree it shouldn't show a state error.

Let's try to show this error in exception field rather than state error in next release. Thank you.

Arpit1496 commented 2 years ago

Hey, I recently got this problem again. But this time, 1st time the socket connects and works perfectly fine. But on navigating back and forth to the same widget throws this error.

Are we supposed dispose something even when using hooks generated by codegen ? Am I missing something ?

MWallenberg commented 2 years ago

@Arpit1496 Thank you very much for sharing the solution about build.yaml. I just ran into this problem - it took a long time for me to diagnose, but thanks to your comment it was a really quick fix. Hope you have an awesome day!

vincenzopalazzo commented 1 year ago

looks like this is a codegen error? we can do something from the client point of view?

vincenzopalazzo commented 1 year ago

closing for lack of response