[Bug]: iOS crash in GMSObjectDataCache Core Data save (fatal optimistic locking failure)
Maintainer antworten meist innerhalb von 5 Tagen
@illuminati1911 arbeitet bereits daran.
Seit 10.9.2026.
Bewertung
Dieses Issue wurde noch nicht bewertet.
Beschreibung
Up front: this is a native SDK bug, filed here because there is nowhere else on GitHub
The defect is in GoogleMaps.framework, which this library pulls in through ios-maps-sdk. I know the bug report template asks for native SDK issues to go to the Cloud support console, and I am happy to also open a case there. I am filing here because issues are disabled on both googlemaps/ios-maps-sdk and googlemaps/ios-navigation-sdk, so there is no public record anywhere that other users of this library can find when they search the crash. Please route it as you see fit.
Description of the bug
The Maps SDK's on-disk map cache (GMSObjectDataCache) saves its Core Data context from more than one context concurrently. When a save hits a conflict its merge policy cannot resolve, Core Data deliberately ends the process:
CoreData: error: fatal: Unable to recover from optimistic locking failure.
It is a hard trap (brk #0x1 at the end of -[NSManagedObjectContext _thereIsNoSadnessLikeTheDeathOfOptimism]), not an Objective-C exception, so no app-side @try/@catch or NSSetUncaughtExceptionHandler can survive it. The app dies on a background queue with no way to intervene.
Stack trace
Crashed thread, named after the managed object context it was running on:
Crashed: NSManagedObjectContext 0x123322280
0 CoreData -[NSManagedObjectContext _thereIsNoSadnessLikeTheDeathOfOptimism] + 192
1 CoreData -[NSManagedObjectContext save:] + 2732
2 <app> -[GMSObjectDataCache internalStoreObjectNamesAndData:version:completionHandler:] + 56936
3 <app> __72-[GMSObjectDataCache storeObjectNamesAndData:version:completionHandler:]_block_invoke_2 + 56672
4 CoreData developerSubmittedBlockToNSManagedObjectContextPerform + 224
5 libdispatch _dispatch_client_callout + 16
6 libdispatch _dispatch_lane_serial_drain + 740
A second thread, NSManagedObjectContext 0x1231b0c00, was inside the same GMSObjectDataCache save at that moment, in -[NSPersistentStore(_NSInternalMethods) _preflightCrossCheck]:
NSManagedObjectContext 0x1231b0c00
0 libsystem_kernel stat64 + 8
2 CoreData -[NSPersistentStore(_NSInternalMethods) _preflightCrossCheck] + 164
3 CoreData __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke.504 + 7228
5 CoreData -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1176
6 CoreData -[NSManagedObjectContext save:] + 1052
7 <app> -[GMSObjectDataCache internalStoreObjectNamesAndData:version:completionHandler:] + 56936
Two of the SDK's contexts writing the cache at the same time is what produces the conflict.
Analysis
Disassembling -[NSManagedObjectContext save:] shows the fatal branch is conditional on the merge policy, not on the conflict:
+2808: add w8, w22, #0x5 ; retry budget
+2816: cmp x9, x8
+2820: b.ls +2900 ; retries left, go round again
+2828: bl objc_msgSend$mergePolicy
+2832: bl objc_msgSend$mergeType
+2836: cbz x0, +2852 ; NSErrorMergePolicyType: log, return a failed save
+2844: bl objc_msgSend$_thereIsNoSadnessLikeTheDeathOfOptimism ; crash
So Core Data only kills the process when the saving context's merge policy reports a merge type other than NSErrorMergePolicyType. The SDK's cache contexts use a trumping policy, which also raises the retry budget from 3 to 1000 attempts (csel w22, w9, w8, eq at +1648) before it gives up. The conflict in this report therefore survived roughly 1000 retries.
Two things that might be worth looking at on the SDK side:
- Why two contexts write
GMSCacheStorage-Objects/Objects.sqliteconcurrently at all. If those writes were serialised the conflict would not arise. - Whether a map data cache should be configured so that an unresolvable conflict is fatal. A failed cache write is recoverable (the tile is re-fetched); ending the host app is not.
The cache in question, from a real app container:
Library/Caches/<bundle id>.GMSCacheStorage/GMSCacheStorage-Objects/Objects.sqlite
Library/Caches/<bundle id>.GMSCacheStorage/GMSCacheStorage-Tiles/Tiles.sqlite
Steps to reproduce
Not reproducible on demand. It arrived from production via Crashlytics on an app that keeps a map on screen for long sessions and swaps between MapView and NavigationView. Triggering it requires a cache conflict the SDK's own merge policy cannot resolve across ~1000 retries, which I have not been able to force.
iOS Platform
Affected.
Android Platform
Not verified. The cache is Core Data, so this specific crash is iOS only.
Versions
@googlemaps/react-native-navigation-sdk: 0.17.1- Native SDKs unchanged from what the library resolves:
ios-maps-sdk11.0.0 andios-navigation-sdk11.0.0 (SPM) - React Native: 0.86.3
- React: 19.2.8
- Symbols confirmed present in the shipped 11.0.0
GoogleMaps.xcframework:GMSObjectDataCache,internalStoreObjectNamesAndData:version:completionHandler:,GMSCacheStorage-%@
Workaround, in case it helps anyone else
There is no configuration knob for this (GMSServices exposes nothing about the cache), but the fatal branch can be made unreachable from the app without touching the SDK. Observe NSManagedObjectContextWillSave, which Core Data posts near the top of save: on the saving context's own queue and before it reads the merge policy, and for contexts whose store lives in the SDK's cache directory, wrap the SDK's policy in one that delegates resolution but reports the error merge type:
private final class NonFatalMergePolicy: NSMergePolicy {
private let wrapped: NSMergePolicy
init(wrapping wrapped: NSMergePolicy) {
self.wrapped = wrapped
super.init(merge: .errorMergePolicyType)
}
override func resolve(mergeConflicts list: [Any]) throws {
try wrapped.resolve(mergeConflicts: list)
}
}
NotificationCenter.default.addObserver(
forName: .NSManagedObjectContextWillSave, object: nil, queue: nil
) { note in
guard let context = note.object as? NSManagedObjectContext,
let policy = context.mergePolicy as? NSMergePolicy,
policy.mergeType != .errorMergePolicyType,
context.persistentStoreCoordinator?.persistentStores
.contains(where: { $0.url?.path.contains("GMSCacheStorage") == true }) == true
else { return }
context.mergePolicy = NonFatalMergePolicy(wrapping: policy)
}
resolveConflicts:error: is still called on the wrapped policy (save: calls it at +2036 regardless of merge type), so the SDK's conflict resolution is unchanged. What changes is that an unresolvable conflict fails that one cache write instead of the process. The retry budget also drops from 1000 to 3, which is a real behaviour change worth knowing about.
I would much rather delete this from our app than carry it, so a fix in the SDK would be very welcome.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 226
- Forks
- 39
- Ø Merge
- 1 T. 20 Std.
- Gemergte PRs (30 T.)
- 7
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus googlemaps/react-native-navigation-sdk
-
[Support Request]: Status of Expo config plugin release (prebuild fails on 0.19.0)Evtl. vergeben @jokerttu hat das vor 2 Tagen übernommen. Offen
googlemaps/react-native-navigation-sdk#711 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 5 Tagen
-
[Bug]: In-navigation notification can't be stoppedEvtl. vergeben @jokerttu hat das vor 8 Tagen übernommen. Offentriage me type: bug
googlemaps/react-native-navigation-sdk#696 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 5 Tagen
-
[Bug]: [iOS] Navigation SDK init/quota retry loop pins the main thread; React Native's Settings module and addMarker's temporary GMSMarker add to the costEvtl. vergeben @illuminati1911 hat das vor 15 Tagen übernommen. Offentriage me type: bug
googlemaps/react-native-navigation-sdk#687 · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 5 Tagen
-
[Bug]: CarPlay map view never sets GMSMapViewOptions.screen, so the navigation header and footer are sized for the phoneEvtl. wieder frei @jokerttu hat das vor 74 Tagen übernommen, und es ist kein Pull Request offen. Offen
googlemaps/react-native-navigation-sdk#640 · 4 Kommentare · 1 Reaktion · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 5 Tagen
-
[Bug]: CarPlay Simulator crashes on iOS versions > 26.3Evtl. wieder frei @jokerttu hat das vor 155 Tagen übernommen, und es ist kein Pull Request offen. Offenpriority: p2 type: bug
googlemaps/react-native-navigation-sdk#607 · 1 Kommentar · 2 zugewiesene Personen ·
Maintainer antworten meist innerhalb von 5 Tagen
Alle Issues in googlemaps/react-native-navigation-sdk
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
home-assistant/frontend#55841 ·
Maintainer antworten meist innerhalb von 1 Tag
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 76/100
lingdojo/kana-dojo#33905 · 1 Kommentar · 5 Reaktionen ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug(semester-planning): the edit application dialog cannot save with an empty «Annet fra bedriften»Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Maintainer antworten meist innerhalb von 1 Tag
-
blocklist removal
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 66/100
MetaMask/eth-phishing-detect#311215 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Explore filter: multi-select value list with allowNewOptions stops accepting values and drops earlier onesEvtl. vergeben @isaac-jaynes-imperva hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
apache/superset#46146 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 2 Tagen