Skip to content

[google_maps_flutter_web] Bad state: Cannot add new events after calling close (with fix proposed) #159388

@andynewman10

Description

@andynewman10

Steps to reproduce

This problem happens with all versions of google_maps_flutter_web, including the most recent one.

  1. create a Flutter web application using google_maps_flutter, with a first page that opens a second page. This second page uses a GoogleMap widget.
  2. pan around the map
  3. go back to the previous page.

This bug is difficult to reproduce, so you may have to insist quite a bit, but it does happen.

Expected results

No exception.

Actual results

In some rare circumstances, the following exception is raised:

DartError: Bad state: Cannot add new events after calling close
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3  throw_errors.dart:296
dart-sdk/lib/async/broadcast_stream_controller.dart 243:24                   add broadcast_stream_controller.dart:243
packages/google_maps_flutter_web/src/google_maps_controller.dart 313:9       <fn> google_maps_controller.dart:313
dart-sdk/lib/async/zone.dart 1594:9                                          runUnaryGuarded zone.dart:1594
dart-sdk/lib/async/stream_impl.dart 365:5                                    [_sendData] stream_impl.dart:365
dart-sdk/lib/async/stream_impl.dart 541:13                                   perform stream_impl.dart:541
dart-sdk/lib/async/stream_impl.dart 646:10                                   handleNext stream_impl.dart:646
dart-sdk/lib/async/stream_impl.dart 617:7                                    callback stream_impl.dart:617
dart-sdk/lib/async/schedule_microtask.dart 40:11                             _microtaskLoop schedule_microtask.dart:40
dart-sdk/lib/async/schedule_microtask.dart 49:5                              _startMicrotaskLoop schedule_microtask.dart:49
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7           <fn> async_patch.dart:181

A similar problem has been reported in the past here

#75818

As far as I can tell, there is nothing user code can do to prevent it from occuring. google_maps_flutter_web code has to be modified in the following way.

All the calls to listen() in _attachMapEvents should memorize the StreamSubscription return value in a member variable and then the stream subscriptions should be cancelled in the dispose() method of GoogleMapController.

In other words, we should have:

import 'package:google_maps/google_maps.dart' as gmaps;

[...]
class GoogleMapController {
  [...]
  // Add member variables
  StreamSubscription<gmaps.MapMouseEventOrIconMouseEvent>? _subOnClick;
  StreamSubscription<gmaps.MapMouseEvent>? _subOnRightClick;
  StreamSubscription<void>? _subOnBoundsChanged;
  StreamSubscription<void>? _subOnIdle;

  void _attachMapEvents(gmaps.Map map) {
    map.onTilesloaded.first.then((void _) {
      // Report the map as ready to go the first time the tiles load
      _streamController.add(WebMapReadyEvent(_mapId));
    });
    _subOnClick= map.onClick.listen((gmaps.MapMouseEventOrIconMouseEvent event) { ... });
    // Do the same for all subscriptions
    [...]
  }

and

  void dispose() {
    // Prior to closing the stream controller, cancel the subscriptions:
    if (_subOnClick != null) {
      _subOnClick!.cancel();
      _subOnClick = null;
    }
    if (_subOnRightClick != null) {
      _subOnRightClick!.cancel();
      _subOnRightClick = null;
    }
    if (_subOnBoundsChanged != null) {
      _subOnBoundsChanged!.cancel();
      _subOnBoundsChanged = null;
    }
    if (_subOnIdle != null) {
      _subOnIdle!.cancel();
      _subOnIdle = null;
    }

    _widget = null;
    _googleMap = null;
    _circlesController = null;
    _heatmapsController = null;
    _polygonsController = null;
    _polylinesController = null;
    _markersController = null;
    _clusterManagersController = null;
    _tileOverlaysController = null;
    _streamController.close();
  }

Note this is an easy, safe and reliable fix.

With the code as it is today, the stream controller may be closed and then, async event handlers may be called and the stream controller used again, raising the exception.

Usually, the exception is raised when in the onBoundsChanged handler.

Code sample

Code sample
[Paste your code here]

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[√] Flutter (Channel stable, 3.24.3, on Microsoft Windows [version 10.0.22000.2538], locale fr-FR)
    • Flutter version 3.24.3 on channel stable at C:\Users\andy\Documents\flutter
    • 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

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at C:\Users\andy\AppData\Local\Android\sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-10027231)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.9.6)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.9.34728.123
    • Windows 10 SDK version 10.0.19041.0

[√] Android Studio (version 2022.2)
    • Android Studio at C:\Users\andy\Documents\Applications\android-studio
    • 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 11.0.15+0-b2043.56-9505619)

[√] Android Studio (version 2022.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • 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-b2043.56-10027231)

[√] IntelliJ IDEA Community Edition (version 2021.3)
    • IntelliJ at C:\Users\andy\Documents\Applications\IntelliJ
    • 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

[√] VS Code (version 1.95.3)
    • VS Code at C:\Users\andy\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.100.0

[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [version 10.0.22000.2538]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 131.0.6778.86
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 131.0.2903.63

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

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    in triagePresently being triaged by the triage teamwaiting for customer responseThe Flutter team cannot make further progress on this issue until the original reporter responds

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions