Skip to content

Null check error on register when state disposed #659

Description

@lpaletta-1

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:

  1. Navigate to a screen that contains a Showcase (a widget with a tutorial/onboarding).
  2. 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.
  3. Wait for the next frame: this fires the post-frame callback _initRootWidget on an already-unmounted State.
  4. 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):

  • OS: N/A

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions