Skip to content

RangeError when both removing listener and disposing ValueNotifier from listener callback #114224

Closed

Description

@spkersten

This code

void main() {
  final vn = ValueNotifier<int>(0);

  void foo() {
    vn.removeListener(foo); // A
    vn.dispose(); // B
  }

  vn.addListener(foo);

  vn.value = 3;
}

results in:

flutter: RangeError (length): Invalid value: Not in inclusive range 0..576460752303423487: -1, #0      new _List (dart:core-patch/array.dart)
#1      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:384:50)
#2      ValueNotifier.value= (package:flutter/src/foundation/change_notifier.dart:463:5)

while I would expect it to work. There is no exception when either line A or line B is removed.

Issue can be fixed by setting also _reentrantlyRemovedListeners to zero in dispose here:

[!] Flutter (Channel unknown, 3.3.2, on macOS 12.5.1 21G83 darwin-arm, locale en-NL)
    ! Flutter version 3.3.2 on channel unknown at /.../flutter
    ! Upstream repository unknown
    • Framework revision e3c29ec00c (6 weeks ago), 2022-09-14 08:46:55 -0500
    • Engine revision a4ff2c53d8
    • Dart version 2.18.1
    • DevTools version 2.15.0

Activity

  1. added
    in triagePresently being triaged by the triage team
    on Oct 31, 2022
  2. huycozy commented on Oct 31, 2022

    @huycozy
    Member

    Hi @spkersten, this issue is reproducible on the latest stable and master channels with provided sample code.
    The error message is a little different from yours. Labeling this issue for further investigation.

    Logs
    RangeError: Invalid array length
    dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 557:30                filled
    packages/flutter/src/foundation/change_notifier.dart 401:50                       notifyListeners
    packages/flutter/src/foundation/change_notifier.dart 489:5                        set value
    packages/reproduce_issues/range_error_114224.dart 12:5                            main
    web_entrypoint.dart 24:31                                                         <fn>
    dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 352:37  _checkAndCall
    dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 357:39  dcall
    lib/ui/initialization.dart 77:15                                                  <fn>
    dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
    dart-sdk/lib/async/zone.dart 1660:54                                              runUnary
    dart-sdk/lib/async/future_impl.dart 147:18                                        handleValue
    dart-sdk/lib/async/future_impl.dart 767:44                                        handleValueCallback
    dart-sdk/lib/async/future_impl.dart 796:13                                        _propagateToListeners
    dart-sdk/lib/async/future_impl.dart 567:5                                         [_completeWithValue]
    dart-sdk/lib/async/future_impl.dart 640:7                                         callback
    dart-sdk/lib/async/schedule_microtask.dart 40:11                                  _microtaskLoop
    dart-sdk/lib/async/schedule_microtask.dart 49:5                                   _startMicrotaskLoop
    dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15               <fn>
    flutter doctor -v (stable and master)
    [✓] Flutter (Channel stable, 3.3.6, on macOS 12.6 21G115 darwin-x64, locale en-VN)
        • Flutter version 3.3.6 on channel stable at /Users/huynq/Documents/GitHub/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 6928314d50 (30 hours ago), 2022-10-25 16:34:41 -0400
        • Engine revision 3ad69d7be3
        • Dart version 2.18.2
        • DevTools version 2.15.0
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
        • Android SDK at /Users/huynq/Library/Android/sdk
        • Platform android-33, build-tools 31.0.0
        • ANDROID_HOME = /Users/huynq/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
        • Xcode at /Applications/Xcode14.0.1.app/Contents/Developer
        • Build 14A400
        • CocoaPods version 1.11.3
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2021.3)
        • 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 11.0.13+0-b1751.21-8125866)
    
    [✓] IntelliJ IDEA Community Edition (version 2022.2.2)
        • IntelliJ at /Applications/IntelliJ IDEA CE.app
        • Flutter plugin version 70.0.5
        • Dart plugin version 222.4167.21
    
    [✓] IntelliJ IDEA Community Edition (version 2022.1.1)
        • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
        • 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.72.2)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.50.0
    
    [✓] Connected device (3 available)
        • SM T225 (mobile) • R9JT3004VRJ • android-arm64  • Android 12 (API 31)
        • macOS (desktop)  • macos       • darwin-x64     • macOS 12.6 21G115 darwin-x64
        • Chrome (web)     • chrome      • web-javascript • Google Chrome 107.0.5304.62
    
    [✓] HTTP Host Availability
        • All required HTTP hosts are available
    
    • No issues found!
    
    [!] Flutter (Channel master, 3.5.0-10.0.pre.166, on macOS 12.6 21G115 darwin-x64, locale en-VN)
        • Flutter version 3.5.0-10.0.pre.166 on channel master at /Users/huynq/Documents/GitHub/flutter_master
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 4f3f932a68 (5 hours ago), 2022-10-30 17:44:24 -0400
        • Engine revision f91119f84f
        • Dart version 2.19.0 (build 2.19.0-353.0.dev)
        • DevTools version 2.18.0
        • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
        • Android SDK at /Users/huynq/Library/Android/sdk
        • Platform android-33, build-tools 31.0.0
        • ANDROID_HOME = /Users/huynq/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
        • Xcode at /Applications/Xcode14.0.1.app/Contents/Developer
        • Build 14A400
        • CocoaPods version 1.11.3
    
    [✓] Chrome - develop for the web
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2021.3)
        • 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 11.0.13+0-b1751.21-8125866)
    
    [✓] IntelliJ IDEA Community Edition (version 2022.2.2)
        • IntelliJ at /Applications/IntelliJ IDEA CE.app
        • Flutter plugin version 70.0.5
        • Dart plugin version 222.4167.21
    
    [✓] IntelliJ IDEA Community Edition (version 2022.1.1)
        • IntelliJ at /Users/huynq/Library/Application Support/JetBrains/Toolbox/apps/IDEA-C/ch-0/221.5591.52/IntelliJ IDEA CE.app
        • 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.72.2)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.50.0
    
    [✓] Connected device (2 available)
        • macOS (desktop) • macos  • darwin-x64     • macOS 12.6 21G115 darwin-x64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 107.0.5304.87
    
    [✓] HTTP Host Availability
        • All required HTTP hosts are available
    
    ! Doctor found issues in 1 category.
    
  3. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    and removed
    in triagePresently being triaged by the triage team
    on Oct 31, 2022
  4. added
    P1High-priority issues at the top of the work list
    on Nov 1, 2022
  5. chunhtai commented on Nov 2, 2022

    @chunhtai
    Contributor

    I think we should disallow calling dispose in the listener callback. https://api.flutter.dev/flutter/foundation/ChangeNotifier/dispose.html
    The document suggest only the owner should call this method.

  6. spkersten commented on Nov 2, 2022

    @spkersten
    ContributorAuthor

    That could be difficult to prevent if a few layers of indirection are present.

  7. chunhtai commented on Nov 2, 2022

    @chunhtai
    Contributor

    If we allows it, it will be hard to manage its lifecycle, and we also need to figure out what would happen after the dispose is called.

    1. the rest of the listeners are still called
      This will require delay dispose which is very error prompt and hard to maintain. and we also need to worry about multiple of them may call dispose as well.
    2. the rest of the listeners are skipped.
      In this case the invoke order would matter, but we don't guarantee invoke order IIRC. So it would create inconsistent behavior.

    I think our current code with your suggestion will be implementing (2).

    I can't think of a case that calling dispose in listener is a valid use case. Do you have any use case that this may be more preferred?

  8. chunhtai commented on Nov 2, 2022

    @chunhtai
    Contributor

    I created #114530, but we should keep the conversation going since this may be a hard breaking change

  9. github-actions commented on Dec 2, 2022

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  10. locked as resolved and limited conversation to collaborators on Dec 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listc: crashStack traces logged to the consolefound in release: 3.3Found to occur in 3.3found in release: 3.5Found to occur in 3.5frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work on

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions