Describe the bug
TypeError: Null check operator used on a null value thrown from inside the showcaseview package (5.1.0), not from our app code.
The crash happens in a post-frame callback that the package schedules in the ShowcaseController.register constructor (showcase_controller.dart:62):
WidgetsBinding.instance.addPostFrameCallback((_) => _initRootWidget());
_initRootWidget() (showcase_controller.dart:277) accesses _context, which is getState().context (showcase_controller.dart:120). When it reaches
State.context (framework.dart:959), the framework performs a null-check on the State's _element. If the Showcase has already been unmounted from the tree
(State no longer mounted) between the moment the callback was scheduled and the next frame being drawn, _element is null and the ! operator throws.
In short: it's a race condition between the showcase registration and the widget being disposed. _initRootWidget does not check mounted before touching
the context (unlike other methods of the same controller such as setupShowcase, which does validate _mounted).
To Reproduce
Steps to reproduce the behavior:
- Navigate to a screen that contains a Showcase (a widget with a tutorial/onboarding).
- Cause that screen to be unmounted immediately (route pop, tab switch, or a rebuild that removes the Showcase) within the same frame it is mounted.
- Wait for the next frame: this fires the post-frame callback _initRootWidget on an already-unmounted State.
- See the error (Null check operator used on a null value).
▎ Note: it's intermittent / timing-dependent, which is why it shows up as a production crash and not consistently.
Expected behavior
The showcase should not crash when the widget is unmounted before the post-frame callback runs. _initRootWidget (and register) should validate
getState().mounted before accessing context, or the callback should abort silently if the showcase is no longer in the tree.
Screenshots
N/A — runtime crash reported via Sentry.
Desktop (please complete the following information):
Smartphone (please complete the following information):
- Device: Android (reported from base.apk)
- OS: Android
- App: app-waiters
- Package: showcaseview: 5.1.0
Additional context
Stacktrace:
TypeError: Null check operator used on a null value
State.context (framework.dart:959)
ShowcaseController._context (showcase_controller.dart:120)
ShowcaseController._initRootWidget (showcase_controller.dart:277)
ShowcaseController.register. (showcase_controller.dart:62)
SchedulerBinding._invokeFrameCallback (binding.dart:1430)
SchedulerBinding.handleDrawFrame (binding.dart:1357)
SentryWidgetsBindingMixin.handleDrawFrame (binding_wrapper.dart:128)
...
- Captured via Sentry (SentryWidgetsBindingMixin).
- Surfaces when upgrading to / using showcaseview 5.1.0.
- Root cause: _initRootWidget accesses State.context in a post-frame callback without checking mounted. Possible app-level workaround: ensure Showcase
widgets are not unmounted in the same frame they're mounted; proper fix: report/patch upstream so that register/_initRootWidget check mounted.
Describe the bug
TypeError: Null check operator used on a null value thrown from inside the showcaseview package (5.1.0), not from our app code.
The crash happens in a post-frame callback that the package schedules in the ShowcaseController.register constructor (showcase_controller.dart:62):
WidgetsBinding.instance.addPostFrameCallback((_) => _initRootWidget());
_initRootWidget() (showcase_controller.dart:277) accesses _context, which is getState().context (showcase_controller.dart:120). When it reaches
State.context (framework.dart:959), the framework performs a null-check on the State's _element. If the Showcase has already been unmounted from the tree
(State no longer mounted) between the moment the callback was scheduled and the next frame being drawn, _element is null and the ! operator throws.
In short: it's a race condition between the showcase registration and the widget being disposed. _initRootWidget does not check mounted before touching
the context (unlike other methods of the same controller such as setupShowcase, which does validate _mounted).
To Reproduce
Steps to reproduce the behavior:
▎ Note: it's intermittent / timing-dependent, which is why it shows up as a production crash and not consistently.
Expected behavior
The showcase should not crash when the widget is unmounted before the post-frame callback runs. _initRootWidget (and register) should validate
getState().mounted before accessing context, or the callback should abort silently if the showcase is no longer in the tree.
Screenshots
N/A — runtime crash reported via Sentry.
Desktop (please complete the following information):
Smartphone (please complete the following information):
Additional context
Stacktrace:
TypeError: Null check operator used on a null value
State.context (framework.dart:959)
ShowcaseController._context (showcase_controller.dart:120)
ShowcaseController._initRootWidget (showcase_controller.dart:277)
ShowcaseController.register. (showcase_controller.dart:62)
SchedulerBinding._invokeFrameCallback (binding.dart:1430)
SchedulerBinding.handleDrawFrame (binding.dart:1357)
SentryWidgetsBindingMixin.handleDrawFrame (binding_wrapper.dart:128)
...
widgets are not unmounted in the same frame they're mounted; proper fix: report/patch upstream so that register/_initRootWidget check mounted.