You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Ticket:**
[MAPSAND-2502](https://mapbox.atlassian.net/browse/MAPSAND-2502?focusedCommentId=658117&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-658117)
Two crashes occur when `MapboxMap` is used inside `LazyColumn` with
Compose 1.7.x (BOM 2025+):
- **Crash 1** — `ComposePausableCompositionException`:
`LazyListPrefetchStrategy` (new in 1.7) uses `PausableComposition` to
pre-compose upcoming items between frames. If the slot is deactivated
while a prefetch is paused, resuming it crashes on the deactivated
nodes.
- **Crash 2** — `place is called on a deactivated node`: during fast
scroll, `measureLazyList` deactivates a slot and then calls `place()` on
its root node in the same synchronous layout pass — before composition
has a chance to clean it up.
### Fix A — `onStop()` before `onDestroy()` in `MapViewLifecycle`
`onDispose` was calling `onDestroy()` directly with no prior `onStop()`.
When a map item scrolls off in a `LazyColumn` the Activity lifecycle
never changes, so the GL render thread was destroyed without being
paused first. Added `mapView.onStop()` before `mapView.onDestroy()`.
Safe — `MapController` guards duplicate calls.
### Fix B — outer `Box(modifier)` as stable slot root (Crash 2)
`Box(modifier)` was inside the `key(composeMapInitOptions)` block.
During fast scroll, `measureLazyList` deactivates the slot and calls
`place()` on the slot root Box (not itself deactivated), which then runs
`placeInBox` on its direct child — the `AndroidView` holder — which IS
deactivated → crash. Moved `Box(modifier)` outside `key()` so the outer
Box is the stable slot root that persists across slot reuse — `key()`
resets the map-specific content while the outer Box LayoutNode remains
the same instance, so SubcomposeLayout has no reason to set `deactivated
= true` on it during the reuse transition. The `AndroidView` holder is
no longer a direct child of the slot root at placement time.
### Customer-side workaround for Crash 1 (PausableComposition)
`ComposePausableCompositionException: Apply is called on deactivated
node` requires the customer to disable `LazyColumn` prefetch with a
no-op `LazyListPrefetchStrategy`. No prefetch = no `PausableComposition`
= crash path doesn't exist. Verified: zero crashes in two test runs
(ornaments on and off) with all three fixes active.
```kotlin
val listState = rememberLazyListState(
prefetchStrategy = object : LazyListPrefetchStrategy {
override fun LazyListPrefetchScope.onScroll(delta: Float, layoutInfo: LazyListLayoutInfo) {}
override fun LazyListPrefetchScope.onVisibleItemsUpdated(layoutInfo: LazyListLayoutInfo) {}
override fun NestedPrefetchScope.onNestedPrefetch(firstVisibleItemIndex: Int) {}
}
)
```
See `agents/specs/lazy_column_compose_crash.md` for full analysis, log
evidence, and stacktrace breakdown.
**Proper fix (after Compose upgrade to 1.4+):** use
`onReset`/`onRelease` callbacks on `AndroidView` to pause/resume the GL
thread instead of destroy/create on each scroll cycle. This also
eliminates the need for the no-op prefetch workaround — Compose 1.4+
handles `AndroidView` deactivation natively.
[MAPSAND-2502]:
https://mapbox.atlassian.net/browse/MAPSAND-2502?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
cc @mapbox/maps-android
cc @mapbox/sdk-platform
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
GitOrigin-RevId: 8c1f3499dc54e66608d47399bcd849c8c4c81871
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,6 +11,8 @@ Mapbox welcomes participation and contributions from everyone.
11
11
## Bug fixes 🐞
12
12
* Fix native memory leak in `AnnotationManager` where bitmap style images were not removed when annotations were deleted.
13
13
* Fix feature ID format mismatch in JNI marshaling where whole-number `double` feature IDs (e.g. `12345.0`) were incorrectly serialized as `"12345.000000"` instead of `"12345"`, causing `setFeatureState` to fail when using IDs obtained from `queryRenderedFeatures`.
14
+
*[compose] Fix `MapboxMap` crash (`place is called on a deactivated node`) when used inside a `LazyColumn`.
15
+
*[compose]**Known limitation:** on Compose Foundation 1.7+ a secondary crash (`Apply is called on deactivated node`) may still occur when `MapboxMap` is used inside a `LazyColumn` during fast scrolling/item reuse because of `LazyColumn` prefetch behavior. Workaround: pass a no-op `LazyListPrefetchStrategy` to `rememberLazyListState()`; see `LazyColumnMapActivity` for an example.
14
16
15
17
# 11.21.0 April 02, 2026
16
18
## Dependencies
@@ -34,7 +36,6 @@ Mapbox welcomes participation and contributions from everyone.
34
36
## Dependencies
35
37
* Update gl-native to [v11.21.0-rc.1](https://github.com/mapbox/mapbox-maps-android/releases/tag/v11.21.0-rc.1), common to [v24.21.0-rc.1](https://github.com/mapbox/mapbox-maps-android/releases/tag/v11.21.0-rc.1).
Copy file name to clipboardExpand all lines: compose-app/src/main/res/values/example_descriptions.xml
+1Lines changed: 1 addition & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -38,4 +38,5 @@
38
38
<stringname="description_animated_3d_model">Animate a 3D airplane model along a flight path with animated propellers, landing gear, and lights using feature state.</string>
39
39
<stringname="description_accessibility_scale">Automatic map symbol scaling based on system font size preferences</string>
40
40
<stringname="description_edge_to_edge">Showcase edge-to-edge layout using Jetpack Compose with proper handling of system insets (system bars, navigation bars, and display cutouts).</string>
41
+
<stringname="description_lazy_column_map">Showcase MapboxMap inside a LazyColumn with correct scroll lifecycle management.</string>
0 commit comments