Describe the Bug
The basic catalog's Modal component (packages/genui/lib/src/catalog/basic_catalog_widgets/modal.dart) opens a bottom sheet using:
widgetBuilder: (itemContext) {
final modalData = _ModalData.fromMap(itemContext.data as JsonMap);
return ElevatedButton(
onPressed: () {
showModalBottomSheet<void>(
context: itemContext.buildContext,
builder: (context) {
return itemContext.buildChild(modalData.content);
},
);
},
child: itemContext.buildChild(modalData.trigger),
);
},
Notice that both itemContext.buildContext and itemContext.buildChild closure over the _SurfaceState that built the trigger widget.
In Flutter, modal bottom sheets are pushed onto the root Navigator / Overlay and have an independent route lifecycle. If the underlying Surface widget is unmounted while the sheet is still open (for example: user navigates to another tab or view, parent widget tree reparents/rebuilds, or host app hides the surface during an asynchronous agent turn), Flutter clears the State (state._element = null).
When any subsequent rebuild occurs inside the open bottom sheet, buildChild calls _buildWidget in surface.dart:
surfaceId: widget.surfaceContext.surfaceId,
Accessing widget on an unmounted State throws:
TypeError: Null check operator used on a null value
_buildWidget catches this exception and returns FallbackWidget, causing the bottom sheet's content to visibly turn into a red "An error occurred / Null check operator used on a null value" error card before dismissing.
Steps to Reproduce
- Render a
Surface containing a Modal component.
- Tap the modal trigger to open the modal bottom sheet.
- While the bottom sheet is displayed, trigger a state change in the host app that unmounts or replaces the parent
Surface widget.
- Interact with or dismiss the modal sheet, or trigger a rebuild inside the sheet.
- See crash /
FallbackWidget displaying Null check operator used on a null value.
Expected Behavior
The modal sheet content should be able to rebuild safely even if the trigger widget's _SurfaceState has been unmounted. Either:
- The modal builder should mount an independent surface or decoupled child renderer tied to the route rather than holding a direct closure on the unmounted
_SurfaceState.
_buildWidget and CatalogItemContext should guard against unmounted state (if (!mounted) return const SizedBox.shrink();) instead of asserting on widget.surfaceContext.
Environment Details
- SDK/Package Name & Version:
package:genui (packages/genui/lib/src/catalog/basic_catalog_widgets/modal.dart, packages/genui/lib/src/widgets/surface.dart)
- Protocol Version: v0.9.1
Describe the Bug
The basic catalog's
Modalcomponent (packages/genui/lib/src/catalog/basic_catalog_widgets/modal.dart) opens a bottom sheet using:Notice that both
itemContext.buildContextanditemContext.buildChildclosure over the_SurfaceStatethat built the trigger widget.In Flutter, modal bottom sheets are pushed onto the root
Navigator/Overlayand have an independent route lifecycle. If the underlyingSurfacewidget is unmounted while the sheet is still open (for example: user navigates to another tab or view, parent widget tree reparents/rebuilds, or host app hides the surface during an asynchronous agent turn), Flutter clears theState(state._element = null).When any subsequent rebuild occurs inside the open bottom sheet,
buildChildcalls_buildWidgetinsurface.dart:surfaceId: widget.surfaceContext.surfaceId,Accessing
widgeton an unmountedStatethrows:_buildWidgetcatches this exception and returnsFallbackWidget, causing the bottom sheet's content to visibly turn into a red "An error occurred / Null check operator used on a null value" error card before dismissing.Steps to Reproduce
Surfacecontaining aModalcomponent.Surfacewidget.FallbackWidgetdisplayingNull check operator used on a null value.Expected Behavior
The modal sheet content should be able to rebuild safely even if the trigger widget's
_SurfaceStatehas been unmounted. Either:_SurfaceState._buildWidgetandCatalogItemContextshould guard against unmounted state (if (!mounted) return const SizedBox.shrink();) instead of asserting onwidget.surfaceContext.Environment Details
package:genui(packages/genui/lib/src/catalog/basic_catalog_widgets/modal.dart,packages/genui/lib/src/widgets/surface.dart)