Skip to content

[maps] MissingPluginException when calling methods on maps instance that has been torn down on the native side #43785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rafaelsimonassi opened this issue Oct 30, 2019 · 93 comments · May be fixed by flutter/packages#9242
Labels
c: crash Stack traces logged to the console customer: crowd Affects or could affect many people, though not necessarily a specific customer. p: maps Google Maps plugin P2 Important issues not at the top of the work list package flutter/packages repository. See also p: labels. team-ecosystem Owned by Ecosystem team triaged-ecosystem Triaged by Ecosystem team

Comments

@rafaelsimonassi
Copy link

rafaelsimonassi commented Oct 30, 2019

Hello, I am experiencing this error below, whenever I use the google map.

Also, please find below the flutter doctor -v output as well.

E/BufferQueueProducer(12362): [SurfaceTexture-0-12362-4] queueBuffer: BufferQueue has been abandoned
E/BufferQueueProducer(12362): [SurfaceTexture-0-12362-4] dequeueBuffer: BufferQueue has been abandoned
E/flutter (12362): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method map#update on channel plugins.flutter.io/google_maps_4)
E/flutter (12362): #0      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:314:7)
E/flutter (12362): <asynchronous suspension>
E/flutter (12362): #1      GoogleMapController._updateMapOptions (package:google_maps_flutter/src/controller.dart:96:19)
E/flutter (12362): <asynchronous suspension>
E/flutter (12362): #2      _GoogleMapState._updateOptions (package:google_maps_flutter/src/google_map.dart:256:16)
E/flutter (12362): <asynchronous suspension>
E/flutter (12362): #3      _GoogleMapState.didUpdateWidget (package:google_maps_flutter/src/google_map.dart:241:5)
E/flutter (12362): #4      StatefulElement.update (package:flutter/src/widgets/framework.dart:4103:58)
E/flutter (12362): #5      Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #6      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #7      Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #8      ProxyElement.update (package:flutter/src/widgets/framework.dart:4254:5)
E/flutter (12362): #9      Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #10     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #11     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #12     ProxyElement.update (package:flutter/src/widgets/framework.dart:4254:5)
E/flutter (12362): #13     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #14     RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4852:32)
E/flutter (12362): #15     MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5243:17)
E/flutter (12362): #16     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #17     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #18     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #19     StatefulElement.update (package:flutter/src/widgets/framework.dart:4120:5)
E/flutter (12362): #20     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #21     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #22     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #23     ProxyElement.update (package:flutter/src/widgets/framework.dart:4254:5)
E/flutter (12362): #24     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #25     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #26     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #27     StatefulElement.update (package:flutter/src/widgets/framework.dart:4120:5)
E/flutter (12362): #28     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #29     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5134:14)
E/flutter (12362): #30     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #31     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #32     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #33     StatelessElement.update (package:flutter/src/widgets/framework.dart:4016:5)
E/flutter (12362): #34     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #35     SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5134:14)
E/flutter (12362): #36     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #37     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #38     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #39     StatefulElement.update (package:flutter/src/widgets/framework.dart:4120:5)
E/flutter (12362): #40     Element.updateChild (package:flutter/src/widgets/framework.dart:2893:15)
E/flutter (12362): #41     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3961:16)
E/flutter (12362): #42     Element.rebuild (package:flutter/src/widgets/framework.dart:3738:5)
E/flutter (12362): #43     StatefulElement.update (package:flutter/src/widgets/framework.dart:4120:5)
E/flutter (12362): #44     Element.updateChild (package:
E/flutter (12362): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)]
[√] Flutter (Channel stable, v1.9.1+hotfix.2, on Microsoft Windows [versão 10.0.18362.418], locale pt-BR)
    • Flutter version 1.9.1+hotfix.2 at c:\src\flutter
    • Framework revision 2d2a1ffec9 (8 weeks ago), 2019-09-06 18:39:49 -0700
    • Engine revision b863200c37
    • Dart version 2.5.0


[√] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at C:\Users\rafas\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
    • All Android licenses accepted.

[√] Android Studio (version 3.5)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 39.0.3
    • Dart plugin version 191.8423
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)

[!] Connected device
    ! No devices available

! Doctor found issues in 1 category.
@ThinkDigitalSoftware
Copy link
Contributor

ThinkDigitalSoftware commented Oct 30, 2019

Have you tried stopping the app and rebuilding it after adding the dependency?

@rafaelsimonassi
Copy link
Author

rafaelsimonassi commented Oct 30, 2019 via email

@BondarenkoStas
Copy link

@rafaelsimonassi I probably miss something, but I wonder, why is there plugins.flutter.io/google_maps_4 not just plugins.flutter.io/google_maps?
Does it work normally when you don't add multiple markers?

@BondarenkoStas BondarenkoStas added p: maps Google Maps plugin plugin waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds labels Oct 30, 2019
@rafaelsimonassi
Copy link
Author

rafaelsimonassi commented Oct 30, 2019 via email

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Oct 30, 2019
@JBBx2016
Copy link
Contributor

I get this too whenever the build function that holds GoogleMap fails. It seems that it causes the map to be removed, and then recreated (with the red error printout). Is there any chance any errors are thrown during build?

@KlausJokisuo
Copy link

To investigate the issue we would need a minimal runnable reproduction as a single file 👍

@SalilLuley
Copy link

What to do in this case? I am getting this error
Unhandled Exception: MissingPluginException(No implementation found for method map#update on channel plugins.flutter.io/google_maps_1)

@vimalmistry
Copy link

Same issue. Any solution found??
plugins.flutter.io/google_maps_0

@KlausJokisuo
Copy link

What to do in this case? I am getting this error
Unhandled Exception: MissingPluginException(No implementation found for method map#update on channel plugins.flutter.io/google_maps_1)

Can you provide us a minimal runnable reproduction as a single file?

@klaszlo8207
Copy link

klaszlo8207 commented Jan 6, 2020

Non-fatal Exception: java.lang.Exception: MissingPluginException(No implementation found for method camera#move on channel plugins.flutter.io/google_maps_1)
       at MethodChannel.invokeMethod(platform_channel.dart:319)
       at GoogleMapController.moveCamera(controller.dart:175)
       at MapMarkerHelper.jumpToMarker.<fn>(map_marker_helper.dart:133)

Hmm, I got a lot of error reporting on this too, in my firebase crashlitycs. But the app not crashing...

my 133 row:

    Utils.doAfterMilliseconds(50, () {
133->      _googleMapController.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(

@KlausJokisuo
Copy link

Non-fatal Exception: java.lang.Exception: MissingPluginException(No implementation found for method camera#move on channel plugins.flutter.io/google_maps_1)
       at MethodChannel.invokeMethod(platform_channel.dart:319)
       at GoogleMapController.moveCamera(controller.dart:175)
       at MapMarkerHelper.jumpToMarker.<fn>(map_marker_helper.dart:133)

Hmm, I got a lot of error reporting on this too, in my firebase crashlitycs. But the app not crashing...

my 133 row:

    Utils.doAfterMilliseconds(50, () {
133->      _googleMapController.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(

Can you provide us a minimal runnable reproduction as a single file?

@klaszlo8207
Copy link

klaszlo8207 commented Jan 7, 2020

I can't it is a production code. Maybe some bug in the system when I change state.

Also maps onCreated is so slow. I am using googlemaps in a pageview. 3 items and animate the pageview index via a timer.periodic 5 seconds.
After oncreate I add 1 marker to it.

Sometimes oncreate takes 2 seconds to refresh.

@KlausJokisuo
Copy link

KlausJokisuo commented Jan 7, 2020

I can't it is a production code. Maybe some bug in the system when I change state.

Also maps onCreated is so slow. I am using googlemaps in a pageview. 3 items and animate the pageview index via a timer.periodic 5 seconds.
After oncreate I add 1 marker to it.

Sometimes oncreate takes 2 seconds to refresh.

Can you give us exact steps when this happens, so we might be able to reproduce the issue. Also does this happen every time

@klaszlo8207
Copy link

klaszlo8207 commented Jan 7, 2020

You can create a sample dart with stateful widget. A Pageview with 3 googlemaps. The 3 googlemap has a controller and 3 different location. After the map oncreated you just add a marker to it and jump to that marker via camera move or animate.

You set a timer.periodic with 5 seconds to animate right the pageview current index and the pageview is infinite.

Thats all.

In my case the 3 location coming from a firestore/or just a google cloud sql via firebase functions. But not that is the probleme...

@klaszlo8207
Copy link

klaszlo8207 commented Jan 7, 2020

I got new exception:

logs
Non-fatal Exception: java.lang.Exception: MissingPluginException(No implementation found for method circles#update on channel plugins.flutter.io/google_maps_163)
       at MethodChannel.invokeMethod(platform_channel.dart:319)
       at GoogleMapController._updateCircles(controller.dart:154)
       at _GoogleMapState._updateCircles(google_map.dart:283)
       at _GoogleMapState.didUpdateWidget(google_map.dart:245)
       at StatefulElement.update(framework.dart:4396)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at RenderObjectElement.updateChildren(framework.dart:5161)
       at MultiChildRenderObjectElement.update(framework.dart:5561)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at SliverMultiBoxAdaptorElement.updateChild(sliver.dart:1288)
       at SliverMultiBoxAdaptorElement.performRebuild.processElement(sliver.dart:1220)
       at SliverMultiBoxAdaptorElement.performRebuild(sliver.dart:1246)
       at SliverMultiBoxAdaptorElement.update(sliver.dart:1191)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at RenderObjectElement.updateChildren(framework.dart:5161)
       at MultiChildRenderObjectElement.update(framework.dart:5561)
       at _ViewportElement.update(viewport.dart:192)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at RenderObjectElement.updateChildren(framework.dart:5161)
       at MultiChildRenderObjectElement.update(framework.dart:5561)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at RenderObjectElement.updateChildren(framework.dart:5161)
       at MultiChildRenderObjectElement.update(framework.dart:5561)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at RenderObjectElement.updateChildren(framework.dart:5161)
       at MultiChildRenderObjectElement.update(framework.dart:5561)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at RenderObjectElement.updateChildren(framework.dart:5161)
       at MultiChildRenderObjectElement.update(framework.dart:5561)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatelessElement.update(framework.dart:4298)
       at Element.updateChild(framework.dart:2977)
       at SingleChildRenderObjectElement.update(framework.dart:5452)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at ProxyElement.update(framework.dart:4557)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at StatefulElement.update(framework.dart:4413)
       at Element.updateChild(framework.dart:2977)
       at ComponentElement.performRebuild(framework.dart:4243)
       at Element.rebuild(framework.dart:3947)
       at BuildOwner.buildScope(framework.dart:2432)
       at WidgetsBinding.drawFrame(binding.dart:773)
       at RendererBinding._handlePersistentFrameCallback(binding.dart:283)
       at SchedulerBinding._invokeFrameCallback(binding.dart:1102)
       at SchedulerBinding.handleDrawFrame(binding.dart:1041)
       at SchedulerBinding._handleDrawFrame(binding.dart:957)

@klaszlo8207
Copy link

So basically I got random_numbers:

/google_maps_163

/google_maps_55

/google_maps_21

/google_maps_4

with error message

@KlausJokisuo
Copy link

KlausJokisuo commented Jan 9, 2020

@klaszlo8207 I think the reason why you get these errors is that the Widget is being rebuilt yet the Controller Completer is already completed once, so the "fresh" Map Widget doesn't have a controller to use.

Couple things to try:

Cache Map widget. (Aka store the Widget into object and return it instead of re-creating it).
Don't use Completer.

@klaszlo8207
Copy link

What I tried:

with AutomaticKeepAliveClientMixin

and

@OverRide
bool get wantKeepAlive => true;

on the child of my pageView

but with no luck. (the pageView animating to the next page and flashing, and not keep the page state)

@klaszlo8207
Copy link

@KlausJokisuo
Copy link

KlausJokisuo commented Jan 11, 2020

https://stackoverflow.com/questions/59693451/flutter-googlemap-in-a-pageview-build-only-once

https://github.com/KlausJokinen/plugins/tree/map_keepAlive

I haven't had time to create PR yet, but you could give it a try. I've implemented keepAlive option into Google Map Widget. (This branch has some other fixes too from flutter/plugins#2458).

@klaszlo8207
Copy link

klaszlo8207 commented Jan 11, 2020

I tried this:

  #google_maps_flutter: ^0.5.21+7
  flutter_plugins:
    git:
      url: git://github.com/KlausJokinen/plugins.git
      ref: map_keepAlive

but I got :


The current Dart SDK version is 2.7.0.


Because my_app depends on flutter_plugins from git which requires SDK version <2.0.0, version solving failed.
pub upgrade failed (1; Because my_app depends on flutter_plugins from git which requires SDK version <2.0.0, version solving failed.)

@holaperdedores
Copy link

@klaszlo8207 en este link sale la respuesta:
https://stackoverflow.com/questions/56351254/flutter-requires-sdk-version

@klaszlo8207
Copy link

@holaperdedores I tried that before. That was the first thing what I tried...

@KlausJokisuo
Copy link

@klaszlo8207

  google_maps_flutter:
    git:
      url: git://github.com/klausjokinen/plugins/
      path: packages/google_maps_flutter
      ref: map_keepAlive

@klaszlo8207
Copy link

klaszlo8207 commented Jan 13, 2020

@KlausJokinen I tried but gave me the same thing. Can you add a sample that is working?

Tha sample what I need:

1 PageView with 3 GoogleMaps, the PageView also infinite PageView

I do not want flashing, but first time when loaded the map. After it I need to cache, or something

@KlausJokisuo
Copy link

KlausJokisuo commented Jan 13, 2020

@klaszlo8207

When you swipe to the different pages the first time it will build the widget, after that it will re-use the "old" one.

code sample
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Map Cache Demo',
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return Scaffold(
      body: PageView(
        children: <Widget>[
          Center(
            child: SizedBox(
              width: size.width * 0.9,
              height: size.height * 0.9,
              child: const GoogleMap(
                keepAlive: true,
                initialCameraPosition: CameraPosition(
                  target: LatLng(-34, 151),
                  zoom: 9.4746,
                ),
              ),
            ),
          ),
          Center(
            child: SizedBox(
              width: size.width * 0.9,
              height: size.height * 0.9,
              child: const GoogleMap(
                keepAlive: true,
                initialCameraPosition: CameraPosition(
                  target: LatLng(40.7128, -74.0060),
                  zoom: 9.4746,
                ),
              ),
            ),
          ),
          Center(
            child: SizedBox(
              width: size.width * 0.9,
              height: size.height * 0.9,
              child: const GoogleMap(
                keepAlive: true,
                initialCameraPosition: CameraPosition(
                  target: LatLng(35.652832, 139.839478),
                  zoom: 9.4746,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
pubspec.yaml
name: map_test
description: Map test.

version: 1.0.0

environment:
  sdk: ">=2.2.2 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter


  google_maps_flutter:
    git:
      url: git://github.com/klausjokinen/plugins/
      path: packages/google_maps_flutter
      ref: map_keepAlive


dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

If you just have a 1 MapWidget which you want to use in 3 different views but load it only once, then what you can do is cache the widget and re-use it. (But with this kind of approach your map configuration must be same in each page).

@millerf

This comment was marked as off-topic.

@masterwok
Copy link

I was able to reproduce this issue consistently on my local machine by doing the following:

  1. Implement a simple map screen that has an asychronous lifecycle operation that invokes a GoogleMapController method after a delay. For example GoogleMap.onMapCreated:
  void _onCameraMove(CameraPosition cameraPosition) async {
    await Future.delayed(const Duration(seconds: 5));
    
    final cameraLocation = await _mapController?.getScreenCoordinate(cameraPosition.target);
  }
  1. Run the application locally as a release build
  2. Navigate into the simple map screen you just created
  3. Move the map and navigate backwards within the 5 second duration
  4. Observe the following error logged to the console:
E/flutter (16217): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: MissingPluginException(No implementation found for method map#getScreenCoordinate on channel plugins.flutter.dev/google_maps_android_0)
E/flutter (16217): #0      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:332)
E/flutter (16217): <asynchronous suspension>
E/flutter (16217): #1      MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart:534)
E/flutter (16217): <asynchronous suspension>
E/flutter (16217): #2      GoogleMapsFlutterAndroid.getScreenCoordinate (package:google_maps_flutter_android/src/google_maps_flutter_android.dart:427)
E/flutter (16217): <asynchronous suspension>
E/flutter (16217): #3      _PartnerLocationsMapState._onCameraMove (package:#####/features/locations/widgets/partner_locations_map/partner_locations_map.dart:231)
E/flutter (16217): <asynchronous suspension>
E/flutter (16217): 

This issue seems to appear when accessing the GoogleMapController after the BuildContext has already been disposed of. One solution is to ensure you set the _mapController instance to null as well as diposing of it first:

  @override
  void dispose() {
    _mapController?.dispose();
    _mapController = null;

    super.dispose();
  }

@SShayashi

This comment was marked as off-topic.

@SShayashi
Copy link

The following report has been occurring on both iOS/Android since Flutter 3.24.

MapsApi.updateTileOverlays
FlutterError - PlatformException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.google_maps_flutter_ios.MapsApi.updateTileOverlays.2"., null, null)

In reference to this comment(#153412 (comment)), the error message has just changed due to the switch to Pigeon for method channel communication.

I can understand this since this issue(#43785) was originally occurring for Android in our production app. However, what I am wondering is that on iOS, this issue(#43785) was not being reported prior to 3.24, but since 3.24, the above report is being generated.

Is iOS reporting a separate issue?

flutter doctor -v
$ flutter doctor -v
[✓] Flutter (Channel stable, 3.24.3, on macOS 14.5 23F79 darwin-arm64, locale ja-JP)
    • Flutter version 3.24.3 on channel stable at /Users/01036096/fvm/versions/3.24.3
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2663184aa7 (2 months ago), 2024-09-11 16:27:48 -0500
    • Engine revision 36335019a8
    • Dart version 3.5.3
    • DevTools version 2.37.3

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/01036096/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = /Users/01036096/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
    • Xcode at /Applications/Xcode-15.4.0.app/Contents/Developer
    • Build 15F31d
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)

[✓] VS Code (version 1.92.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.100.0

[✓] Connected device (4 available)
    • iPhone 15 Pro (mobile)          • 15AEE00E-9941-4F6F-BBEE-312A4D8BF51F • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-1
      (simulator)
    • macOS (desktop)                 • macos                                • darwin-arm64   • macOS 14.5 23F79 darwin-arm64
    • Mac Designed for iPad (desktop) • mac-designed-for-ipad                • darwin         • macOS 14.5 23F79 darwin-arm64
    • Chrome (web)                    • chrome                               • web-javascript • Google Chrome 131.0.6778.86

[✓] Network resources
    • All expected network resources are available.

• No issues found!

@KTBsomen
Copy link

what is the sollution

E/flutter (21352): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.google_maps_flutter_android.MapsApi.animateCamera.0"., null, null)
E/flutter (21352): #0      MapsApi.animateCamera (package:google_maps_flutter_android/src/messages.g.dart:2162:7)
E/flutter (21352): <asynchronous suspension>
E/flutter (21352): 
D/MapsInitializer(21352): preferredRenderer: null
D/zzcc    (21352): preferredRenderer: null

@filiph
Copy link
Contributor

filiph commented May 5, 2025

Minimal (single-file) repro — inspired by @masterwok's comment above:

Code

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GoogleMap Bug Repro',
      home: const MainMenuScreen(),
    );
  }
}

class MainMenuScreen extends StatelessWidget {
  const MainMenuScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const MapScreen()),
            );
          },
          child: const Text('Open MapScreen'),
        ),
      ),
    );
  }
}

class MapScreen extends StatefulWidget {
  const MapScreen({super.key});

  @override
  State<MapScreen> createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  GoogleMapController? _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Move map, then go back'),
      ),
      body: GoogleMap(
        initialCameraPosition: CameraPosition(
          target: LatLng(50.073658, 14.418540),
          zoom: 12.0,
        ),
        onMapCreated: (controller) {
          _controller = controller;
        },
        onCameraMove: (position) async {
          await Future.delayed(const Duration(seconds: 5));

          final controller = _controller!;

          // This is where the bug is: we might be accessing controller
          // of a map that has already been disposed.
          final cameraLocation = await controller.getLatLng(
            ScreenCoordinate(x: 0, y: 0),
          );
          debugPrint('Camera moved to $cameraLocation');
        },
      ),
    );
  }
}

I'm looking into submitting a fix for this.

It sounds like there may be an opportunity here to have the plugin help manage in-flight operations (e.g., by having this error be silently dropped for disposed instances).

@stuartmorgan-g

There are a few ways to achieve this, and a few details I'd like to clarify.

Ways to do this:

  1. Every relevant public method in GoogleMapController gets a guard clause like the following:
  Future<void> doSomething(...) {
    if (_disposed) return;
    GoogleMapsFlutterPlatform.instance.doSomething(...);
  }
  1. Every platform package deals with this on its own. For example, GoogleMapsFlutterAndroid ignores calls to its methods when the map has been disposed, as does GoogleMapsFlutterIOS.

  2. Every method in GoogleMapsFlutterPlatform currently looks like this:

      Future<void> doSomething(...) {
        throw UnimplementedError('...');
      }

    Instead, it could be this:

      Future<void> doSomething(...) {
        if (_disposed) return;
        return doSomethingImpl(...);
      }

I'd go with option 1 but I don't want to assume anything.


A separate question is about what to do in the event of users calling methods on maps that are disposed.

  1. Ignore silently.
  2. Log a warning using pkg:logging.
  3. Throw a custom error, such as UseAfterDisposedException.

I'd prefer option 2 myself. Option 1 completely breaks the Fail-Fast principle and could lead to developers being suprised that their calls have no effect. Option 3 is the most "correct", imho, but leads to a lot of boilerplate around every method call. Option 2 depends on people using the Dart team's pkg:logging package (or some of its community extensions) to learn about possible issues in their code. But at least there's a chance they'll get notified.

@stuartmorgan-g
Copy link
Contributor

Minimal (single-file) repro

I don't think that repro is a case we need to solve at the plugin level; the bug is in the repro code. Clients should not be doing arbitrary delayed interaction with widgets they may themselves be disposing without checks.

The problem that should be fixed at the plugin level is the set of cases where the plugin itself does delayed calls to other plugin methods (e.g., callbacks from the native side), which clients of the plugin can't control.

@filiph
Copy link
Contributor

filiph commented May 5, 2025

I don't think that repro is a case we need to solve at the plugin level; the bug is in the repro code. Clients should not be doing arbitrary delayed interaction with widgets they may themselves be disposing without checks.

Ah, sorry, I didn't realize this. From the bug reports above, I got the sense that people get in trouble when inadvertently calling methods on disposed maps. Hence all the talk about PageViews, Firebase callbacks, workarounds involving setting _controller to null, keep-alives, and so on.

cases where the plugin itself does delayed calls to other plugin methods (e.g., callbacks from the native side)

Do you have an example? I can't find this in the reports and stacktraces above (but it's quite possible I'm looking wrong). Should I be looking at files like packages/google_maps_flutter/google_maps_flutter_android/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java and searching for unguarded async calls there? It would be helpful to have a stacktrace for this.

@stuartmorgan-g
Copy link
Contributor

Do you have an example? I can't find this in the reports and stacktraces above

I thought there were cases of callbacks from native, but looking back maybe it was just artificial delays introduced in callback handlers.

However, the initial report appears to be a call from within the plugin, even if not from within a native callback—unless someone manually disposed the controller while the widget still existed, but that seems relatively unlikely.

@filiph
Copy link
Contributor

filiph commented May 5, 2025

I'm a bit lost here. Are you suggesting I focus on the initial report only? That one is from 2019 and the stacktrace has methods _updateOptions() and _updateMapOptions() that no longer exist. Should I try to follow the history to that version? Do we ignore the other reports in this issue since then, or move them elsewhere? If that's the case, does it make sense to prioritize this issue?

@stuartmorgan-g
Copy link
Contributor

I'm saying that there are two potential ways of getting this exception:

  1. Code within the plugin that itself does async things without verifying that the instance still exists
  2. Code that is written by clients of the plugin, which assume that it can unconditionally use a map controller even after the widget and controller have been disposed.

Any instances of 1 are a valid bug in the plugin, and should be fixed by silently dropping whatever the call is. Any instances of 2 are bugs in the client code.

Re-reading, it looks like you want to try to make the experience of 2 better, whereas I was thinking about actually fixing 1. For client code, if we want to make the error more explicit, 3 seems like the best option, except that it would be an Error type, not an Exception type, because it's a programming error. I'm not sure what you mean by "a lot of boilerplate around every method call"; could you elaborate on that part?

@filiph
Copy link
Contributor

filiph commented May 5, 2025

Thanks for the clarification.

Yes, I was referring to the second way to get the exception, since it's what most of the commenters on this thread seem to be reporting. It seems you prefer to address the first way instead? That's valid, of course. It would be helpful to know what you think as a maintainer:

  1. Is this issue fixed when both ways are addressed? Only the first one?
  2. Should this issue be split in two?
  3. If I'm to address the first way to get the exception, where do I start? Is there perhaps another (linked) issue that has a stacktrace with way 1?
  4. Or is this a theoretical exception at this point and we want to make sure it never happens in the future by way of defensive coding.

I'm not sure what you mean by "a lot of boilerplate around every method call"; could you elaborate on that part?

I was referring to try-catch blocks around every call, or some app state that tracks disposal of the controller (since afaik there is no field or getter on the controller to check whether the instance has been disposed). So, for example:

final cameraLocation = await controller.getLatLng(screen);

becomes

if (controllerDisposed) return;
final cameraLocation = await _controller.getLatLng(screen);

Admittedly not a lot of boilerplate in this case, but in more complex cases where we can't just return, it could mean more code than that.

@stuartmorgan-g
Copy link
Contributor

I was referring to try-catch blocks around every call

There's no scenario where clients should be writing try/catch to handle calling into a disposed object; they should not be making the call in the first place. We would not throw exceptions intentionally, because it's a programming error.

or some app state that tracks disposal of the controller (since afaik there is no field or getter on the controller to check whether the instance has been disposed).

I'm not sure I follow. The only way to call a disposed controller would be to have a long-lived controller reference. Why would the client solution not be to simply null out that reference when the controller is disposed? I don't see why additional state would be required.

@stuartmorgan-g
Copy link
Contributor

  1. Is this issue fixed when both ways are addressed? Only the first one?
  2. Should this issue be split in two?
  3. If I'm to address the first way to get the exception, where do I start? Is there perhaps another (linked) issue that has a stacktrace with way 1?
  4. Or is this a theoretical exception at this point and we want to make sure it never happens in the future by way of defensive coding.

If we don't actually have any instances of current errors within the plugin, we can treat this as just covering improving the client error. I may have just misread a stack during triage and thought we did have a plugin error somewhere.

@filiph
Copy link
Contributor

filiph commented May 6, 2025

I'm not sure I follow. The only way to call a disposed controller would be to have a long-lived controller reference. Why would the client solution not be to simply null out that reference when the controller is disposed? I don't see why additional state would be required.

You're right. I thought maybe the client might want to distinguish between controller being null because it hasn't been assigned to yet, and between controller being null because it's been disposed. But I think we can safely assume that all other callbacks (like onCameraMove) will always be called after onMapCreated, so I can't imagine a scenario where this distinction would be useful. Apologies for over-complicating this.

@JamesMcIntosh
Copy link

JamesMcIntosh commented May 8, 2025

@stuartmorgan-g Looking back at the stack trace for the original issue, it stems from a didUpdateWidget, inside this method there are many calls to update the map using the controller.

  void didUpdateWidget(GoogleMap oldWidget) {
    super.didUpdateWidget(oldWidget);
    _updateOptions();
    _updateClusterManagers();
...
  }

Each of these methods follow this pattern

  Future<void> _updateX() async {
    final GoogleMapController controller = await _controller.future;
    unawaited(controller._doSomething()));
  }

Each time there is awaiting for the GoogleMapController it opens the door for the map instance to have been disposed before the controller method is called.

There should be a mounted check before calling the controller method and I'll also recommend to lookup and reuse the controller by passing it into these update methods.

I have tested and verified that this is the problem by adding logging to didUpdateWidget and dispose.

For me this error occurs very often on the web version of our Flutter app as it is easy to switch pages while the map is still initializing.

I'm just added a PR now to address this - #9227

@JamesMcIntosh
Copy link

This is the one of the exceptions caused when the controller has been disposed when calling didUpdateWidget.
The stack can be any of the update methods inside didUpdateWidget.

UnknownMapIDError
Unknown map ID 0
google_maps_flutter_ios.dart in GoogleMapsFlutterIOS._hostApi at line 73 within google_maps_flutter_ios
google_maps_flutter_ios.dart in GoogleMapsFlutterIOS.updatePolygons at line 248 within google_maps_flutter_ios
controller.dart in GoogleMapController._updatePolygons at line 144 within google_maps_flutter
google_map.dart in _GoogleMapState._updatePolygons at line 477 within google_maps_flutter

This is the other exception which I observed where the controller is looked up after the GoogleMapsController.init future completes and calls _updateTileOverlays

Assertion failed: file:///Users/james/.pub-cache/hosted/pub.dev/google_maps_flutter_web-0.5.12/lib/src/google_maps_flutter_web.dart:32:12
controller != null
"Maps cannot be retrieved before calling buildView!"
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 307:3  throw_
dart-sdk/lib/_internal/js_dev_runtime/private/profile.dart 117:39            assertFailed
packages/google_maps_flutter_web/src/google_maps_flutter_web.dart 32:22      [_map]
packages/google_maps_flutter_web/src/google_maps_flutter_web.dart 107:17     <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 622:19          <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 647:23          <fn>
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 541:3           _asyncStartSync
packages/google_maps_flutter_web/src/google_maps_flutter_web.dart 103:16     updateTileOverlays
packages/google_maps_flutter/src/controller.dart 188:10                      [_updateTileOverlays]
packages/google_maps_flutter/src/google_map.dart 519:25                      <fn>
...
Future<void> onPlatformViewCreated(int id) async {
    final GoogleMapController controller = await GoogleMapController.init(
      id,
      widget.initialCameraPosition,
      this,
    );
    _controller.complete(controller);
    unawaited(_updateTileOverlays());

@filiph
Copy link
Contributor

filiph commented May 12, 2025

I'm just added a PR now to address this - #9227

Was this link perhaps garbled? It links to an issue that seems unrelated at first glance.

@JamesMcIntosh
Copy link

I'm just added a PR now to address this - #9227

Was this link perhaps garbled? It links to an issue that seems unrelated at first glance.

I've fixed up the link as the PR is in the packages repository

flutter/packages#9227

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: crash Stack traces logged to the console customer: crowd Affects or could affect many people, though not necessarily a specific customer. p: maps Google Maps plugin P2 Important issues not at the top of the work list package flutter/packages repository. See also p: labels. team-ecosystem Owned by Ecosystem team triaged-ecosystem Triaged by Ecosystem team
Projects
None yet