Skip to content

Infinite MapCamera.zoom (caused by fitting to zero-area bounds) causes errors in TileLayer #2135

@EtzBetz

Description

@EtzBetz

What is the bug?

In our app, when I create a CameraFit with CameraFit.bounds() from a single LatLng Point, without setting the maxZoom Parameter, and then set it as initialCameraFit or fit and move to it afterwards, the app will crash with the following error log:

flutter: Unsupported operation: Infinity or NaN toInt
flutter: #0      double.toInt (dart:core-patch/double.dart)
flutter: #1      double.round (dart:core-patch/double.dart:196:34)
flutter: #2      _TileLayerState._clampToNativeZoom (package:flutter_map/src/layer/tile_layer/tile_layer.dart:749:12)
flutter: #3      _TileLayerState._onTileUpdateEvent (package:flutter_map/src/layer/tile_layer/tile_layer.dart:654:22)
flutter: #4      _RootZone.runUnaryGuarded (dart:async/zone.dart:1778:10)
flutter: #5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381:11)
flutter: #6      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:312:7)
flutter: #7      _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:67:11)
flutter: #8      _EventSinkWrapper.add (dart:async/stream_transformers.dart:13:11)
flutter: #9      TileUpdateTransformers.ignoreTapEvents.<anonymous closure> (package:flutter_map/src/layer/tile_layer/tile_update_transformer.dart:54:42)
flutter: #10     _HandlerEventSink.add (dart:async/stream_transformers.dart:230:17)
flutter: #11     _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:115:24)
flutter: #12     _RootZone.runUnaryGuarded (dart:async/zone.dart:1778:10)
flutter: #13     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381:11)
flutter: #14     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:312:7)
flutter: #15     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:154:11)
flutter: #16     _MapStream._handleData (dart:async/stream_pipe.dart:252:10)
flutter: #17     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:184:13)
flutter: #18     _RootZone.runUnaryGuarded (dart:async/zone.dart:1778:10)
flutter: #19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381:11)
flutter: #20     _DelayedData.perform (dart:async/stream_impl.dart:573:14)
flutter: #21     _PendingEvents.handleNext (dart:async/stream_impl.dart:678:11)
flutter: #22     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:649:7)
flutter: #23     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
flutter: #24     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
flutter:

======== Exception caught by widgets library =======================================================
The following UnsupportedError was thrown building TileLayer(dirty, dependencies: [MapInheritedModel], state: _TileLayerState#e6131(tickers: tracking 24 tickers)):
Unsupported operation: Infinity or NaN toInt

The relevant error-causing widget was: 
  TileLayer TileLayer:file:///Users/<removed>/Documents/Coding/Flutter/<removed>/lib/ui/home_map_page.dart:115:32
When the exception was thrown, this was the stack: 
#0      double.toInt (dart:core-patch/double.dart)
#1      double.round (dart:core-patch/double.dart:196:34)
#2      _TileLayerState.build (package:flutter_map/src/layer/tile_layer/tile_layer.dart:544:37)
#3      StatefulElement.build (package:flutter/src/widgets/framework.dart:5823:27)
#4      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5715:15)
#5      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5874:11)
#6      Element.rebuild (package:flutter/src/widgets/framework.dart:5427:7)
#7      BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2694:15)
#8      BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752:11)
#9      BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056:18)
#10     _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:272:12)
#11     RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:335:38)
#12     RenderObjectWithLayoutCallbackMixin.runLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:4160:33)
#13     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:2885:17)
#14     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1209:15)
#15     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2884:14)
#16     RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4160:5)
#17     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:449:5)
#18     RenderObject.layout (package:flutter/src/rendering/object.dart:2766:7)
#19     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#20     RenderObject.layout (package:flutter/src/rendering/object.dart:2766:7)
#21     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:180:12)
#22     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1118:7)
#23     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:249:7)
#24     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:419:14)
#25     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2614:7)
#26     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1160:18)
#27     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1173:15)
#28     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:629:23)
#29     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1242:13)
#30     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#31     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1438:15)
#32     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1351:9)
#33     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1204:5)
#34     _invoke (dart:ui/hooks.dart:331:13)
#35     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:444:5)
#36     _drawFrame (dart:ui/hooks.dart:303:31)
====================================================================================================
Lost connection to device.

Logging the CameraFit lat,lng and zoom, they will be NaN, NaN, Infinity respectively in this case.
If you need more info, I'm happy to help.

How can we reproduce it?

Use this CameraFit

final cameraFit = CameraFit.bounds(
 padding: const EdgeInsets.all(60),
 // maxZoom: 15,
 bounds: LatLngBounds.fromPoints([
   const LatLng(40.93284460740569, -4.14985273673187),
   // const LatLng(45.66265214844347, 10.61577200201736),
]));

with e.g. this layer:

final children = <Widget>[];
  children.add(TileLayer(
    urlTemplate:
      "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
      userAgentPackageName: '<removed>',
));

with this map

FlutterMap(
  mapController: _mapController,
 options: MapOptions(
    initialRotation: 0.0,
    initialZoom: 13.0,
    initialCameraFit: cameraFit,
  ),
  children: children,
),

To "manually" fix it, uncomment the maxZoom or the 2nd marker parameter.

Do you have a potential solution?

I am not sure what is happening in the code, but since there is one marker and with that no distance to cover, the zoom can be infinitely high in theory. I guess there should be some relatively high maxZoom to cover this crash? The experience will then still eventually be bad if there is no maxZoom set, but the app wont crash by itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P: 3 (low)(Default priority for feature requests)

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions