Status Update
Comments
gr...@geodb.com <gr...@geodb.com> #2
This is probably happening because there are multiple instances of DataStore active. You should consider managing the DataStore as a singleton. See the attached bug for more info.
yb...@google.com <yb...@google.com> #3
by any chance, the app is in boot receiver mode (hence it is not un-locked yet)? or is it repeatedly happening for a group of users?
gr...@geodb.com <gr...@geodb.com> #4
Most interaction with the app is user initiated touching the launcher icon. There are a few push notifications but they just start the app through a pending intent, OS is going to ask to unlock before launching that.
I decided to patch the problem through the following corruption handler:
actual fun getReplaceFileCorruptionHandler(): ReplaceFileCorruptionHandler<Preferences>? {
return ReplaceFileCorruptionHandler { exception ->
platformLog.w(TAG, "Silencing Corruption!", exception)
emptyPreferences()
}
}
Since then, these users are advancing and hitting now another problem with Firebase instantiation, which I'm using com.google.firebase:firebase-bom:32.7.1
:
Fatal Exception: java.lang.RuntimeException: Unable to get provider com.google.firebase.provider.FirebaseInitProvider: androidx.datastore.core.CorruptionException: Unable to parse preferences proto.
at android.app.ActivityThread.installProvider(ActivityThread.java:7468)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:6980)
…
Caused by androidx.datastore.core.CorruptionException: Unable to parse preferences proto.
at androidx.datastore.preferences.PreferencesMapCompat$Companion.readFrom(PreferencesMapCompat.kt:34)
at androidx.datastore.preferences.core.PreferencesSerializer.readFrom(PreferencesSerializer.jvm.kt:46)
at androidx.datastore.core.okio.OkioReadScope.readData$suspendImpl(OkioStorage.kt:180)
at androidx.datastore.core.okio.OkioReadScope.readData(OkioStorage.kt:1)
at androidx.datastore.core.StorageConnectionKt$readData$2.invokeSuspend(StorageConnection.kt:74)
at androidx.datastore.core.StorageConnectionKt$readData$2.invoke(StorageConnection.kt:1)
at androidx.datastore.core.StorageConnectionKt$readData$2.invoke(StorageConnection.kt:2)
at androidx.datastore.core.okio.OkioStorageConnection.readScope(OkioStorage.kt:113)
at androidx.datastore.core.StorageConnectionKt.readData(StorageConnection.kt:74)
at androidx.datastore.core.DataStoreImpl.readDataFromFileOrDefault(DataStoreImpl.kt:289)
at androidx.datastore.core.DataStoreImpl.access$getStorage$p(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl.access$readDataFromFileOrDefault(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl$InitDataStore.readDataOrHandleCorruption(DataStoreImpl.kt:414)
at androidx.datastore.core.DataStoreImpl$InitDataStore.access$readDataOrHandleCorruption(DataStoreImpl.kt:329)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invokeSuspend(DataStoreImpl.kt:346)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invoke(DataStoreImpl.kt:2)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invoke(DataStoreImpl.kt:1)
at androidx.datastore.core.SingleProcessCoordinator.lock(SingleProcessCoordinator.kt:41)
at androidx.datastore.core.DataStoreImpl$InitDataStore.doRun(DataStoreImpl.kt:343)
at androidx.datastore.core.RunOnce.runIfNeeded(DataStoreImpl.kt:474)
at androidx.datastore.core.DataStoreImpl.readAndInitOrPropagateAndThrowFailure(DataStoreImpl.kt:218)
at androidx.datastore.core.DataStoreImpl.access$getStorage$p(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl.access$readAndInitOrPropagateAndThrowFailure(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl$readState$2.invokeSuspend(DataStoreImpl.kt:170)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
…
Caused by androidx.datastore.preferences.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).
at androidx.datastore.preferences.protobuf.CodedInputStream$StreamDecoder.readTag(CodedInputStream.java:2116)
at androidx.datastore.preferences.protobuf.CodedInputStreamReader.getFieldNumber(CodedInputStreamReader.java:82)
at androidx.datastore.preferences.protobuf.MessageSchema.mergeFromHelper(MessageSchema.java:3913)
at androidx.datastore.preferences.protobuf.MessageSchema.mergeFrom(MessageSchema.java:3895)
at androidx.datastore.preferences.protobuf.GeneratedMessageLite.parsePartialFrom(GeneratedMessageLite.java:1647)
at androidx.datastore.preferences.protobuf.GeneratedMessageLite.parseFrom(GeneratedMessageLite.java:1783)
at androidx.datastore.preferences.PreferencesProto$PreferenceMap.parseFrom(PreferencesProto.java:194)
at androidx.datastore.preferences.PreferencesMapCompat$Companion.readFrom(PreferencesMapCompat.kt:32)
at androidx.datastore.preferences.core.PreferencesSerializer.readFrom(PreferencesSerializer.jvm.kt:46)
at androidx.datastore.core.okio.OkioReadScope.readData$suspendImpl(OkioStorage.kt:180)
at androidx.datastore.core.okio.OkioReadScope.readData(OkioStorage.kt:1)
at androidx.datastore.core.StorageConnectionKt$readData$2.invokeSuspend(StorageConnection.kt:74)
at androidx.datastore.core.StorageConnectionKt$readData$2.invoke(StorageConnection.kt:1)
at androidx.datastore.core.StorageConnectionKt$readData$2.invoke(StorageConnection.kt:2)
at androidx.datastore.core.okio.OkioStorageConnection.readScope(OkioStorage.kt:113)
at androidx.datastore.core.StorageConnectionKt.readData(StorageConnection.kt:74)
at androidx.datastore.core.DataStoreImpl.readDataFromFileOrDefault(DataStoreImpl.kt:289)
at androidx.datastore.core.DataStoreImpl.access$getStorage$p(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl.access$readDataFromFileOrDefault(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl$InitDataStore.readDataOrHandleCorruption(DataStoreImpl.kt:414)
at androidx.datastore.core.DataStoreImpl$InitDataStore.access$readDataOrHandleCorruption(DataStoreImpl.kt:329)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invokeSuspend(DataStoreImpl.kt:346)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invoke(DataStoreImpl.kt:2)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invoke(DataStoreImpl.kt:1)
at androidx.datastore.core.SingleProcessCoordinator.lock(SingleProcessCoordinator.kt:41)
at androidx.datastore.core.DataStoreImpl$InitDataStore.doRun(DataStoreImpl.kt:343)
at androidx.datastore.core.RunOnce.runIfNeeded(DataStoreImpl.kt:474)
at androidx.datastore.core.DataStoreImpl.readAndInitOrPropagateAndThrowFailure(DataStoreImpl.kt:218)
at androidx.datastore.core.DataStoreImpl.access$getStorage$p(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl.access$readAndInitOrPropagateAndThrowFailure(DataStoreImpl.kt:46)
at androidx.datastore.core.DataStoreImpl$readState$2.invokeSuspend(DataStoreImpl.kt:170)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
…
I'm attaching the full stacktrace.
Current firebase statistics of the crash show for the last 90 days 1862 crashes for 93 different users. Devices have shifted now to 88% Samsung, 6% Oppo, 2% Motorola. It's unclear to me if these users get the crash all the time or it is something that happens once in a while.
yb...@google.com <yb...@google.com> #5
by any chance this is related to boot mode? Does your app support direct boot?
gr...@geodb.com <gr...@geodb.com> #6
No, no.
zh...@google.com <zh...@google.com> #7
After another pass, I think the problem might be on-disk file being corrupted so the proto parser gets InvalidProtocolBufferException
when read from that file, so having ReplaceFileCorruptionHandler
as mentioned in CorruptionException
was not handled by the handler should be fixed recently in 1.1.0-beta02
as
hy...@costco.com <hy...@costco.com> #8
Are there any updates on this?
CodedInputStream$StreamDecoder.readTag
Fatal Exception: androidx.datastore.core.CorruptionException: Unable to parse preferences proto.
at androidx.datastore.preferences.PreferencesMapCompat$Companion.readFrom(PreferencesMapCompat.kt:34)
at androidx.datastore.preferences.core.PreferencesSerializer.readFrom(PreferencesSerializer.jvm.kt:46)
at androidx.datastore.core.okio.OkioReadScope.readData$suspendImpl(OkioStorage.kt:180)
at androidx.datastore.core.okio.OkioReadScope.readData(OkioStorage.kt)
at androidx.datastore.core.StorageConnectionKt$readData$2.invokeSuspend(StorageConnection.kt:74)
at androidx.datastore.core.StorageConnectionKt$readData$2.invoke(StorageConnection.kt:1)
at androidx.datastore.core.StorageConnectionKt$readData$2.invoke(StorageConnection.kt:2)
at androidx.datastore.core.okio.OkioStorageConnection.readScope(OkioStorage.kt:113)
at androidx.datastore.core.StorageConnectionKt.readData(StorageConnection.kt:74)
at androidx.datastore.core.DataStoreImpl.readDataFromFileOrDefault(DataStoreImpl.kt:331)
at androidx.datastore.core.DataStoreImpl.readDataOrHandleCorruption(DataStoreImpl.kt:373)
at androidx.datastore.core.DataStoreImpl.access$readDataOrHandleCorruption(DataStoreImpl.kt)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invokeSuspend(DataStoreImpl.kt:445)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invoke(DataStoreImpl.kt:2)
at androidx.datastore.core.DataStoreImpl$InitDataStore$doRun$initData$1.invoke(DataStoreImpl.kt:1)
at androidx.datastore.core.SingleProcessCoordinator.lock(SingleProcessCoordinator.kt:41)
at androidx.datastore.core.DataStoreImpl$InitDataStore.doRun(DataStoreImpl.kt:442)
at androidx.datastore.core.RunOnce.runIfNeeded(DataStoreImpl.kt:505)
at androidx.datastore.core.DataStoreImpl.readAndInitOrPropagateAndThrowFailure(DataStoreImpl.kt:274)
at androidx.datastore.core.DataStoreImpl.handleUpdate(DataStoreImpl.kt:251)
at androidx.datastore.core.DataStoreImpl.access$handleUpdate(DataStoreImpl.kt)
at androidx.datastore.core.DataStoreImpl$writeActor$3.invokeSuspend(DataStoreImpl.kt:215)
at androidx.datastore.core.DataStoreImpl$writeActor$3.invoke(DataStoreImpl.kt:1)
at androidx.datastore.core.DataStoreImpl$writeActor$3.invoke(DataStoreImpl.kt:2)
at androidx.datastore.core.SimpleActor$offer$2.invokeSuspend(SimpleActor.kt:121)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt)
ks...@godaddy.com <ks...@godaddy.com> #9
We're experiencing a very similar, if not the same, problem.
Fatal Exception: java.lang.RuntimeException: Unable to create application com.pairip.application.Application: h2.c: Unable to parse preferences proto.
h2.c
is an obfuscated androidx.datastore.core.CorruptionException
Interestingly enough, we're getting these crashes on Xiaomi (84%) and Vivo (16%) devices only, Android 13 and Android 14, 100% in background.
el...@google.com <el...@google.com> #10
Hi there, we have multiple issues open for this same issue, so to consolidate the info on 1 issue tracker, I will be closing this issue "as duplicate".
Description
DataStore Component used: androidx.datastore:datastore-preferences-core
DataStore Version used: 1.1.0-alpha06
Devices/Android versions reproduced on:
The crashes happen at the startup of the app, less than 1 second in (according to Firebase). I have no specific sample code to show other than having a few preference values and this init code:
This class is instantiated as a sigleton using koin.
The crashes I'm getting from firebase (https://console.firebase.google.com/project/wallace-e0b5d/crashlytics/app/android:com.geodb.wallace/issues/a2cf628a24bbb0a6dc43bd3eaea9e642?time=last-seven-days&sessionEventKey=654740DA02A200012FCC588E54B5ED42_1876318630322353543 ) all look like these:
Unfortunately after implementing datastore around 5 users have got stuck by this and they can't launch the app. Unless these crashes are sporadic, I expect these users to hate us to death because they can't access their crypto wallets any more if they can't launch the app, and I see no remediation other than going back on using datastore.
Also, despite using the shared preferences library I was surprised to see anything protobuf related in the crash, but then I guess that's your internal thing and the shared preferences is just a wrapper api.