Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Random ServerException #465

@Masadow

Description

@Masadow

While on production, I receive random errors both in android and web (I haven't tested other platforms)

On web, it resembles to :

ServerException(originalException: ClientException: XMLHttpRequest error., uri=https://api.v2.medami.fr, originalStackTrace: Error
    at Object.ccc (https://patient.v2.medami.fr/main.dart.js:8636:19)
    at bJ9.$1 (https://patient.v2.medami.fr/main.dart.js:124760:63)
    at Object.cPc (https://patient.v2.medami.fr/main.dart.js:7401:19)
    at b4v.<anonymous> (https://patient.v2.medami.fr/main.dart.js:318907:10)
    at bxv.q7 (https://patient.v2.medami.fr/main.dart.js:70756:12)
    at cGj.$0 (https://patient.v2.medami.fr/main.dart.js:70021:11)
    at Object.atE (https://patient.v2.medami.fr/main.dart.js:7263:40)
    at aS.ld (https://patient.v2.medami.fr/main.dart.js:69941:3)
    at cOb.$0 (https://patient.v2.medami.fr/main.dart.js:70546:20)
    at Object.cPa (https://patient.v2.medami.fr/main.dart.js:7395:19), parsedResponse: null)

On android :

ServerException(originalException: ClientException with SocketException: Software caused connection abort (OS Error: Software caused connection abort, errno = 103), address = api.v2.medami.fr, port = 44844, uri=https://api.v2.medami.fr, originalStackTrace: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
pid: 18642, tid: 18715, name 1.ui
os: android arch: arm64 comp: yes sim: no
build_id: 'b866ace19d6955e3f7dae5b7ee781c6c'
isolate_dso_base: 7036011000, vm_dso_base: 7036011000
isolate_instructions: 7036377580, vm_instructions: 7036361000
    #00 abs 000000703712b433 virt 000000000111a433 _kDartIsolateSnapshotInstructions+0xdb3eb3
<asynchronous suspension>
    #01 abs 00000070371179f3 virt 00000000011069f3 _kDartIsolateSnapshotInstructions+0xda0473
<asynchronous suspension>
    #02 abs 00000070371174cb virt 00000000011064cb _kDartIsolateSnapshotInstructions+0xd9ff4b
<asynchronous suspension>
    #03 abs 0000007037117133 virt 0000000001106133 _kDartIsolateSnapshotInstructions+0xd9fbb3
<asynchronous suspension>
, parsedResponse: null)

I've seen another issue (#358) but I doubt it's linked to CORS since my error is random and not systematic + it also occurs on android.

Relevant code :

await gql.client.request(GGetStepReq((b) => b..vars.id = stepId)).first

gql being of class

import 'package:flutter/widgets.dart';
import 'package:ferry/ferry.dart';
import 'package:ferry_hive_store/ferry_hive_store.dart';
import 'package:hive/hive.dart';
import 'package:gql_exec/src/request.dart';
import 'package:medami_utils/services/auth.dart';
import 'package:medami_utils/services/graphql/log.dart';
import 'package:provider/provider.dart';

class GraphQLClient extends ChangeNotifier {
  static late final Cache cache;
  static late final String endpoint;
  static late final Function(Request request, LinkException e) logError;
  late Client client;
  String? token;

  static init(String endpoint, Function(Request request, LinkException e) logError) async {
    GraphQLClient.endpoint = endpoint;
    GraphQLClient.logError = logError;

    final box = await Hive.openBox("graphql");

    final store = HiveStore(box);

    cache = Cache(store: store);
  }

  void build(String? token) {
    this.token = token;
    
    client = Client(
      link: HttpLinkWithLog(endpoint, token, logError),
      cache: cache,
      defaultFetchPolicies: {
        OperationType.query: FetchPolicy.NetworkOnly,
      }
    );

    notifyListeners();
  }
}

class GraphQL extends StatelessWidget {
  GraphQL({super.key, required this.child});

  final GraphQLClient _graphql = GraphQLClient();
  final AuthToken _auth = AuthToken();

  final Widget Function(GraphQLClient) child;

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => _auth,
      child: Consumer<AuthToken>(
        builder: (context, authToken, c) {
          print('rebuild graphql client with token: ${authToken.value}');
          _graphql.build(authToken.value);
          return c!;
        },
        child: ChangeNotifierProvider(
          create: (context) => _graphql,
          child: child(_graphql),
        ),
      ),
    );
  }
}

Custom httplink to log link errors globally

import 'dart:async';

import 'package:ferry/ferry.dart';
import 'package:gql_exec/src/request.dart';
import 'package:gql_exec/src/response.dart';
import 'package:gql_http_link/gql_http_link.dart';

class HttpLinkWithLog extends HttpLink {
  HttpLinkWithLog(endpoint, token, this.logError) : super(
    endpoint,
    defaultHeaders: {
      if (token !=  null) 'Authorization': token,
    },
  );

  Function(Request request, LinkException e) logError;

  @override
  Stream<Response> request(
    Request request, [
    NextLink? forward,
  ]) async* {
    final controller = StreamController<Response>();

    Future<void>(() async {
      try {
        await for (final response in super.request(request)) {
          controller.add(response);
        }
      } on LinkException catch (e) {
        logError(request, e);
        controller.addError(e);
      } finally {
        await controller.close();
      }
    });

    yield* controller.stream;
  }
}

The graphql object is not being rebuilt when the error occured so it can't be the cause of the issue too

At this point, I have no idea where to look at to understand and fix the issue.

Since it's very random (happen maybe 1/50), it's impossible for me to build a small repro as well

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions