On iOS, _MapWidgetState.onPlatformViewCreated reads key.currentContext?.size while the platform view can be mounted but not yet laid out. Element.size throws RenderBox was not laid out in that state — the ?. only guards a null context, not an unlaid-out element. Because onPlatformViewCreated is async with no await before the read, the synchronous throw is captured into a Future that DarwinViewState._createNewUiKitView discards along with its try/catch — so the error surfaces as an unhandled-zone fatal that no app-side try/catch can intercept, with zero app frames in the trace.
Affected code
lib/src/map_widget.dart — present at least from 2.18.0 (line 329) through 2.23.0 (line 337) and still unguarded in 2.28.0 (line 350):
Future<void> onPlatformViewCreated(int id) async {
...
// WARNING: Because platform view is not sized at this moment on iOS,
// it is not safe to call methods that depend on the size of the platform view,
...
final size = key.currentContext?.size; // <-- throws when mounted but not laid out
if (size != null) {
await _mapboxMapsPlatform.submitViewSizeHint(
width: size.width, height: size.height);
}
...
}
The method's own WARNING comment already states the view is not sized at this moment — but Element.size on a render box whose layout has not completed does not return null; it throws.
Reproduction shape
A MapWidget mounts while a route transition is still in flight (e.g. a screen containing the map is pushed and the platform view is created before first layout of the new route completes). We see this in production crash reporting (Sentry) as level: fatal, RenderBox was not laid out, with no application frames — which is exactly the discarded-Future mechanism above. 7 events / 5 distinct users on our iOS build over ~1 week, reproducing across app versions.
Suggested fix
Any of:
- guard the read:
final ctx = key.currentContext; final box = ctx?.findRenderObject(); final size = (box is RenderBox && box.hasSize) ? box.size : null;
- defer the size-hint to a post-frame callback when layout hasn't completed;
- or make the read part of an awaited chain so a failure is at least observable/handleable rather than an unhandled zone error.
The size hint is an optimization, so a null/deferred fallback is safe — considerably safer than an uncatchable fatal.
On iOS,
_MapWidgetState.onPlatformViewCreatedreadskey.currentContext?.sizewhile the platform view can be mounted but not yet laid out.Element.sizethrowsRenderBox was not laid outin that state — the?.only guards a null context, not an unlaid-out element. BecauseonPlatformViewCreatedisasyncwith noawaitbefore the read, the synchronous throw is captured into aFuturethatDarwinViewState._createNewUiKitViewdiscards along with its try/catch — so the error surfaces as an unhandled-zone fatal that no app-sidetry/catchcan intercept, with zero app frames in the trace.Affected code
lib/src/map_widget.dart— present at least from 2.18.0 (line 329) through 2.23.0 (line 337) and still unguarded in 2.28.0 (line 350):The method's own
WARNINGcomment already states the view is not sized at this moment — butElement.sizeon a render box whose layout has not completed does not returnnull; it throws.Reproduction shape
A
MapWidgetmounts while a route transition is still in flight (e.g. a screen containing the map is pushed and the platform view is created before first layout of the new route completes). We see this in production crash reporting (Sentry) aslevel: fatal,RenderBox was not laid out, with no application frames — which is exactly the discarded-Future mechanism above. 7 events / 5 distinct users on our iOS build over ~1 week, reproducing across app versions.Suggested fix
Any of:
final ctx = key.currentContext; final box = ctx?.findRenderObject(); final size = (box is RenderBox && box.hasSize) ? box.size : null;The size hint is an optimization, so a null/deferred fallback is safe — considerably safer than an uncatchable fatal.