Commit cb4f3cd
Fix PointAnnotationClusterActivity NPE crash on invalid HTTP response (#10413)
## Summary
Fixes: https://mapbox.atlassian.net/browse/MAPSAND-2547
- Fix NPE crash in `PointAnnotationClusterActivity` when the network
request for GeoJSON data returns an error response
- Add HTTP error checking in `AnnotationUtils.loadStringFromNet()` to
return `null` on non-2xx responses instead of passing a null/empty body
downstream
- Add GeoJSON parse error handling with user-facing `Toast` messages in
both the `app` and `compose-app` examples
## Problem
Reported via mobot tests on Samsung Galaxy S22, Android 13,
v11.19.0-beta.1. The examples app crashes with `NullPointerException:
Null type` when tapping "Add Cluster Symbol Annotations".
#### Root cause analysis from logcat
1. The ArcGIS URL (`opendata.arcgis.com`) returns a **301 redirect** to
`hub.arcgis.com`, which intermittently serves non-GeoJSON content (HTML
error pages instead of the expected `.geojson` response).
2. `loadStringFromNet()` **never checks `response.isSuccessful`** — it
reads the response body unconditionally, even on 4xx/5xx error codes.
The HTML error page is returned as a valid `String`.
3. The HTML string is passed directly to `FeatureCollection.fromJson()`,
which throws an NPE because there is no `"type"` field in the response
(AutoValue's generated code performs a null check on the required `type`
property).
4. Two identical crashes occurred **39 seconds apart** with different
PIDs, confirming the endpoint was consistently returning bad content
during that time window.
5. The 551 "Unable to make space for entry" cache warning messages
visible in the same logcat are **unrelated** — they originate from
maps-core's tile cache on a different thread, triggered by an earlier
offline download, and are not connected to this crash.
## Solution
Check `response.isSuccessful` in `AnnotationUtils` before reading the
body, returning `null` early on HTTP errors. In both
`PointAnnotationClusterActivity` variants, null-check the result before
parsing, wrap JSON parsing in a `try/catch`, and show a `Toast` on
failure. The Compose variant also removes the now-unnecessary
`suspendCancellableCoroutine`/`ExperimentalCoroutinesApi` wrapper.
## Key Changes
- **`AnnotationUtils.loadStringFromNet()`** (`app` + `compose-app`):
Check `response.isSuccessful`; log and return `null` on HTTP errors.
Replace manual `BufferedReader`/`StringBuilder` with
`response.body?.string()`.
- **`app/.../markersandcallouts/PointAnnotationClusterActivity`**:
Null-check `loadStringFromNet()` result, wrap
`FeatureCollection.fromJson()` in `try/catch`, show `Toast` on failure,
add `TAG` constant.
- **`compose-app/.../annotation/PointAnnotationClusterActivity`**: Same
null/parse error handling; refactored `loadData()` from
`suspendCancellableCoroutine` to a plain `fun` returning `emptyList()`
on failure; removed `@OptIn(ExperimentalCoroutinesApi::class)`.
- **Imports**: Replaced wildcard `java.io.*` with explicit imports in
both `AnnotationUtils` files.
## Test plan
- [x] Manually test `PointAnnotationClusterActivity` in `app` with
network available
- [x] Manually test `PointAnnotationClusterActivity` in `compose-app`
with network available
- [x] Manually test with network disabled to confirm `Toast` error
message appears
cc @mapbox/sdk-platform
cc @mapbox/maps-android
GitOrigin-RevId: fc93f22b63f964e2375915d626614b00b28efb2e1 parent 9b23e92 commit cb4f3cd
File tree
5 files changed
+57
-33
lines changed- app/src/main/java/com/mapbox/maps/testapp/examples
- annotation
- markersandcallouts
- compose-app/src/main/java/com/mapbox/maps/compose/testapp/examples
- annotation
- utils
5 files changed
+57
-33
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
12 | 15 | | |
13 | 16 | | |
14 | 17 | | |
| |||
Lines changed: 7 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | | - | |
| 13 | + | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
125 | 124 | | |
126 | | - | |
| 125 | + | |
127 | 126 | | |
128 | 127 | | |
129 | 128 | | |
| |||
Lines changed: 17 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
141 | 142 | | |
142 | 143 | | |
143 | 144 | | |
144 | | - | |
145 | | - | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
146 | 155 | | |
147 | 156 | | |
148 | 157 | | |
149 | 158 | | |
150 | 159 | | |
151 | 160 | | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
152 | 166 | | |
153 | 167 | | |
154 | 168 | | |
| |||
159 | 173 | | |
160 | 174 | | |
161 | 175 | | |
| 176 | + | |
162 | 177 | | |
163 | 178 | | |
164 | 179 | | |
| |||
Lines changed: 21 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
38 | | - | |
39 | | - | |
40 | 39 | | |
41 | 40 | | |
42 | 41 | | |
| |||
152 | 151 | | |
153 | 152 | | |
154 | 153 | | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
169 | 166 | | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
170 | 174 | | |
171 | 175 | | |
172 | 176 | | |
173 | 177 | | |
| 178 | + | |
174 | 179 | | |
175 | 180 | | |
176 | 181 | | |
| |||
Lines changed: 9 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
11 | 14 | | |
12 | 15 | | |
13 | 16 | | |
| |||
112 | 115 | | |
113 | 116 | | |
114 | 117 | | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
120 | 122 | | |
121 | | - | |
| 123 | + | |
122 | 124 | | |
123 | 125 | | |
124 | 126 | | |
| |||
0 commit comments