Flutter Firebase Performance - unhandled exception

849

This is known issue : https://github.com/FirebaseExtended/flutterfire/issues/1136

This is happening because the URL is ending with "?". removing it as suggested in issue will solve the problem.

From Issue:

Removing the trailing ? fixes the issue

    var strUri = request.url.toString();
    strUri = strUri.endsWith("?") ? strUri.substring(0, strUri.length - 1): strUri;

    final HttpMetric metric = FirebasePerformance.instance.newHttpMetric(strUri, ...); ```

For the code in question the solution should be:

String encodeUrlParams(String url, Map<String, dynamic> params) {
    Uri uri = Uri.parse(url);
    if (uri.hasQuery) params.addAll(uri.queryParameters);
    uri = uri.replace(queryParameters: params);
    final uriStr = uri.toString();
    return uriStr.endsWith("?")
        ? uriStr.substring(0, uriStr.length - 1)
        : uriStr;
  }
Share:
849
Harsh Bhikadia
Author by

Harsh Bhikadia

curious-mind.

Updated on December 15, 2022

Comments

  • Harsh Bhikadia
    Harsh Bhikadia over 1 year

    Getting an error while tracking HTTPMetric. It was working properly

    Check the traceback below:

    /flutter (10311): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, String index out of range: -1, null)
    E/flutter (10311): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:569:7)
    E/flutter (10311): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:316:33)
    E/flutter (10311): <asynchronous suspension>
    E/flutter (10311): #2      FirebasePerformance.newHttpMetric (package:firebase_performance/src/firebase_performance.dart:76:33)
    E/flutter (10311): #3      _Client.send (package:<my_package>/api/api.dart:226:10)
    E/flutter (10311): #4      _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    E/flutter (10311): #5      _Client.send (package:<my_package>/api/api.dart:224:37)
    E/flutter (10311): #6      BaseClient._sendUnstreamed (package:http/src/base_client.dart:169:38)
    E/flutter (10311): #7      _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    E/flutter (10311): #8      BaseClient._sendUnstreamed (package:http/src/base_client.dart:149:35)
    E/flutter (10311): #9      BaseClient.post (package:http/src/base_client.dart:54:7)
    E/flutter (10311): #10    MyAPI.post.<anonymous closure> (package:<my_package>/api/home.dart:17:33)
    E/flutter (10311): #11     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:71:64)
    E/flutter (10311): #12     _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (10311): #13     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (10311): #14     _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
    E/flutter (10311): #15     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
    E/flutter (10311): #16     Future._propagateToListeners (dart:async/future_impl.dart:707:32)
    E/flutter (10311): #17     Future._completeWithValue (dart:async/future_impl.dart:522:5)
    E/flutter (10311): #18     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:30:15)
    E/flutter (10311): #19     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:288:13)
    E/flutter (10311): #20     BaseAPI.buildAuthHeaders (package:<my_package>/api/api.dart)
    E/flutter (10311): #21     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:71:64)
    E/flutter (10311): #22     _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (10311): #23     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (10311): #24     _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
    E/flutter (10311): #25     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
    E/flutter (10311): #26     Future._propagateToListeners (dart:async/future_impl.dart:707:32)
    E/flutter (10311): #27     Future._completeWithValue (dart:async/future_impl.dart:522:5)
    E/flutter (10311): #28     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:552:7)
    E/flutter (10311): #29     _rootRun (dart:async/zone.dart:1124:13)
    E/flutter (10311): #30     _CustomZone.run (dart:async/zone.dart:1021:19)
    E/flutter (10311): #31     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
    E/flutter (10311): #32     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
    E/flutter (10311): #33     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
    E/flutter (10311): #34     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
    E/flutter (10311): 
    I/flutter (10311): Error caught: MissingPluginException(No implementation found for method HttpMetric#start on channel plugins.flutter.io/firebase_performance)
    I/flutter (10311): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:314:7)
    I/flutter (10311): <asynchronous suspension>
    I/flutter (10311): #1      HttpMetric.start (package:firebase_performance/src/http_metric.dart:131:40)
    I/flutter (10311): #2      _Client.send (package:<my_package>/api/api.dart:228:18)
    I/flutter (10311): #3      _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    I/flutter (10311): #4      _Client.send (<my_package>/api/api.dart:224:37)
    I/flutter (10311): #5      BaseClient._sendUnstreamed (package:http/src/base_client.dart:169:38)
    I/flutter (10311): #6      _AsyncAwaitCompleter.start (dart:async-patch/async_patch.dart:43:6)
    I/flutter (10311): #7      BaseClient._sendUnstreamed (package:http/src/base_client.dart:149:35)
    I/flutter (10311): #8      BaseClient.post (package:http/src/base_client.dart:54:7)
    I/flutter (10311): #9      MyAPI.post.<anonymous closure> (package<my_package>/api/home.dart:17:33)
    I/flutter (10311): #10     _asyncThenWrapperHelper.<anonymous closure> (dart:async-patch/async_patch.dart:71:64)
    I/flutter (10311): #11    
    

    Following is my setup

    abstract class BaseAPI {
      _Client client = _Client(http.Client());
    
      String encodeUrlParams(String url, Map<String, String> params) {
        Uri uri = Uri.parse(url);
        if (uri.hasQuery) params.addAll(uri.queryParameters);
        uri = uri.replace(queryParameters: params);
        return uri.toString();
      }
    
      String appendPath(String url, List pathSegments) {
        final pathSeg = pathSegments.map((ps) => ps.toString()).join("/");
        return url.endsWith("/") ? "$url$pathSeg/" : "$url/$pathSeg/";
      }
    
      Map<String, String> buildBasicHeaders() {
        return {
          HttpHeaders.contentTypeHeader: "application/json",
          HttpHeaders.acceptHeader: "application/json",
        };
      }
    }
    
    class _Client extends http.BaseClient {
      _Client(this._inner);
    
      final http.Client _inner;
    
      HttpMethod _nameToEnum(String methodName) {
        switch (methodName) {
          case "GET":
            return HttpMethod.Get;
          case "POST":
            return HttpMethod.Post;
          case "HEAD":
            return HttpMethod.Head;
          case "PUT":
            return HttpMethod.Put;
          case "DELETE":
            return HttpMethod.Delete;
          default:
            return HttpMethod.Get;
        }
      }
    
      @override
      Future<http.StreamedResponse> send(http.BaseRequest request) async {
        final HttpMetric metric = FirebasePerformance.instance
            .newHttpMetric(request.url.toString(), _nameToEnum(request.method));
    
        await metric.start();
    
        http.StreamedResponse response;
        try {
          response = await _inner.send(request);
          metric
            ..responsePayloadSize = response.contentLength
            ..responseContentType = response.headers['Content-Type']
            ..requestPayloadSize = request.contentLength
            ..httpResponseCode = response.statusCode;
        } finally {
          await metric.stop();
        }
    
        return response;
      }
    }
    
    

    It was working properly before, suddenly it is throwing this error.

    • Harsh Bhikadia
      Harsh Bhikadia over 4 years
      @FrankvanPuffelen added some code to start with.