Skip to content

Conversation

karolinaoparczyk
Copy link

@karolinaoparczyk karolinaoparczyk commented Jul 22, 2025

Problem

Widgets could encounter runtime errors when setState() was called on unmounted widgets. This typically occurred in asynchronous callbacks, handler events, or during widget disposal, leading to exceptions.

Test case There is a list item that has a `FlutterSlider` and a delete button on it. Try deleting the list item while sliding.
setState exception and stacktrace
I/flutter ( 6518): │ ⛔ ══╡ EXCEPTION CAUGHT BY GESTURE LIBRARY ╞════════════════════════
I/flutter ( 6518): │ ⛔ The following assertion was thrown while dispatching a pointer
I/flutter ( 6518): │ ⛔ event:
I/flutter ( 6518): │ ⛔ setState() called after dispose():
I/flutter ( 6518): │ ⛔ _FlutterSliderState#64efb(lifecycle state: defunct, not mounted,
I/flutter ( 6518): │ ⛔ tickers: tracking 0 tickers)
I/flutter ( 6518): │ ⛔ This error happens if you call setState() on a State object for a
I/flutter ( 6518): │ ⛔ widget that no longer appears in the widget tree (e.g., whose
I/flutter ( 6518): │ ⛔ parent widget no longer includes the widget in its build). This
I/flutter ( 6518): │ ⛔ error can occur when code calls setState() from a timer or an
I/flutter ( 6518): │ ⛔ animation callback.
I/flutter ( 6518): │ ⛔ The preferred solution is to cancel the timer or stop listening
I/flutter ( 6518): │ ⛔ to the animation in the dispose() callback. Another solution is
I/flutter ( 6518): │ ⛔ to check the "mounted" property of this object before calling
I/flutter ( 6518): │ ⛔ setState() to ensure the object is still in the tree.
I/flutter ( 6518): │ ⛔ This error might indicate a memory leak if setState() is being
I/flutter ( 6518): │ ⛔ called because another object is retaining a reference to this
I/flutter ( 6518): │ ⛔ State object after it has been removed from the tree. To avoid
I/flutter ( 6518): │ ⛔ memory leaks, consider breaking the reference to this object
I/flutter ( 6518): │ ⛔ during dispose().
I/flutter ( 6518): │ ⛔
I/flutter ( 6518): │ ⛔ When the exception was thrown, this was the stack:
I/flutter ( 6518): │ ⛔ #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1163:9)
I/flutter ( 6518): │ ⛔ #1      State.setState (package:flutter/src/widgets/framework.dart:1198:6)
I/flutter ( 6518): │ ⛔ #2      _FlutterSliderState._leftHandlerMove (package:flutter_xlider/src/view/flutter_slider_widget.dart:1045:5)
I/flutter ( 6518): │ ⛔ #3      _FlutterSliderState._leftHandlerWidget.<anonymous closure> (package:flutter_xlider/src/view/flutter_slider_widget.dart:1482:11)
I/flutter ( 6518): │ ⛔ #4      RenderPointerListener.handleEvent (package:flutter/src/rendering/proxy_box.dart:3203:44)
I/flutter ( 6518): │ ⛔ #5      GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:499:22)
I/flutter ( 6518): │ ⛔ #6      RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:473:11)
I/flutter ( 6518): │ ⛔ #7      GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:437:7)
I/flutter ( 6518): │ ⛔ #8      GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:394:5)
I/flutter ( 6518): │ ⛔ #9      GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:341:7)
I/flutter ( 6518): │ ⛔ #10     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:308:9)
I/flutter ( 6518): │ ⛔ #11     _invoke1 (dart:ui/hooks.dart:347:13)
I/flutter ( 6518): │ ⛔ #12     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:467:7)
I/flutter ( 6518): │ ⛔ #13     _dispatchPointerDataPacket (dart:ui/hooks.dart:282:31)
I/flutter ( 6518): │ ⛔
I/flutter ( 6518): │ ⛔ Event:
I/flutter ( 6518): │ ⛔   PointerMoveEvent#63f14(position: Offset(234.0, 236.0))
I/flutter ( 6518): │ ⛔ Target:
I/flutter ( 6518): │ ⛔   RenderPointerListener#9fa4a DISPOSED
I/flutter ( 6518): │ ⛔ ═════════════════════════════════════════════════════════════════
I/flutter ( 6518): │ ⛔


AnimationController exception and stacktrace
I/flutter (25189): │ ⛔ ══╡ EXCEPTION CAUGHT BY GESTURE LIBRARY ╞════════════════════════
I/flutter (25189): │ ⛔ The following assertion was thrown while dispatching a pointer
I/flutter (25189): │ ⛔ event:
I/flutter (25189): │ ⛔ AnimationController.stop() called after
I/flutter (25189): │ ⛔ AnimationController.dispose()
I/flutter (25189): │ ⛔ AnimationController methods should not be used after calling
I/flutter (25189): │ ⛔ dispose.
I/flutter (25189): │ ⛔ 'package:flutter/src/animation/animation_controller.dart':
I/flutter (25189): │ ⛔ Failed assertion: line 901 pos 7: '_ticker != null'
I/flutter (25189): │ ⛔
I/flutter (25189): │ ⛔ Either the assertion indicates an error in the framework itself,
I/flutter (25189): │ ⛔ or we should provide substantially more information in this error
I/flutter (25189): │ ⛔ message to help you determine and fix the underlying cause.
I/flutter (25189): │ ⛔ In either case, please report this assertion by filing a bug on
I/flutter (25189): │ ⛔ GitHub:
I/flutter (25189): │ ⛔   https://github.com/flutter/flutter/issues/new?template=02_bug.yml
I/flutter (25189): │ ⛔
I/flutter (25189): │ ⛔ When the exception was thrown, this was the stack:
I/flutter (25189): │ ⛔ #2      AnimationController.stop (package:flutter/src/animation/animation_controller.dart:901:7)
I/flutter (25189): │ ⛔ #3      AnimationController.value= (package:flutter/src/animation/animation_controller.dart:373:5)
I/flutter (25189): │ ⛔ #4      AnimationController.reset (package:flutter/src/animation/animation_controller.dart:394:5)
I/flutter (25189): │ ⛔ #5      _FlutterSliderState._stopHandlerAnimation (package:flutter_xlider/src/view/flutter_slider_widget.dart:1723:19)
I/flutter (25189): │ ⛔ #6      _FlutterSliderState._leftHandlerWidget.<anonymous closure> (package:flutter_xlider/src/view/flutter_slider_widget.dart:1528:11)
I/flutter (25189): │ ⛔ #7      RenderPointerListener.handleEvent (package:flutter/src/rendering/proxy_box.dart:3204:40)
I/flutter (25189): │ ⛔ #8      GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:499:22)
I/flutter (25189): │ ⛔ #9      RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:473:11)
I/flutter (25189): │ ⛔ #10     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:437:7)
I/flutter (25189): │ ⛔ #11     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:394:5)
I/flutter (25189): │ ⛔ #12     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:341:7)
I/flutter (25189): │ ⛔ #13     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:308:9)
I/flutter (25189): │ ⛔ #14     _invoke1 (dart:ui/hooks.dart:347:13)
I/flutter (25189): │ ⛔ #15     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:467:7)
I/flutter (25189): │ ⛔ #16     _dispatchPointerDataPacket (dart:ui/hooks.dart:282:31)
I/flutter (25189): │ ⛔ (elided 2 frames from class _AssertionError)
I/flutter (25189): │ ⛔
I/flutter (25189): │ ⛔ Event:
I/flutter (25189): │ ⛔   PointerUpEvent#669dd(position: Offset(174.8, 299.0))
I/flutter (25189): │ ⛔ Target:
I/flutter (25189): │ ⛔   RenderPointerListener#55efa DISPOSED
I/flutter (25189): │ ⛔ ═════════════════════════════════════════════════════════════════
I/flutter (25189): │ ⛔

Solution

Added if (!mounted) early return checks at the entry point of all methods that could be called asynchronously or during widget disposal. This single approach protects against both setState and AnimationController errors.

This change improves widget stability and prevents crash scenarios in production apps.

@karolinaoparczyk karolinaoparczyk changed the title Fix: Add mounted checks before setState calls to prevent runtime errors Fix: Add mounted checks to prevent widget lifecycle errors Jul 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant