Repository navigation
"UniFFI API checksum mismatch" in LWK bindings on armeabi-v7a #317
Description
Title
Crash at login on 32-bit ARM (armeabi-v7a): "UniFFI API checksum mismatch" in LWK bindings
Summary
The app crashes immediately when logging in (PIN) on a 32-bit ARM device. The crash comes from the LWK UniFFI integrity check failing when LwkNetworkBackend calls lwk.Network.mainnet(). The same wallet type works on a 64-bit (arm64-v8a) device.
This looks like the known gobley 0.3.7 bug on 32-bit ARM Android (gobley/gobley#252). It was fixed in LWK on 2026-10-09 (Blockstream/lwk@22659e7), but that fix is still listed as "Unreleased" in LWK's changelog. Green currently depends on LWK 0.19.0.
Environment
- App: Blockstream App (Green),
com.greenaddress.greenbits_android_wallet, version [5.7.0] from Play Store - Device: Xiaomi Redmi A1 (MediaTek Helio A22), Android 12 Go edition
- ABI:
armeabi-v7a(ro.product.cpu.abilist= armeabi-v7a,armeabi - Works on: Xiaomi Redmi 12 (arm64-v8a)
Steps to reproduce
- Install the app on a 32-bit ARM (armeabi-v7a) device.
- Let the app be AOT-compiled (Play cloud profile at install, or background dexopt).
- Open or create a wallet with pin
- The app crashes.
Expected
Login succeeds.
Actual
Fatal crash:
java.lang.ExceptionInInitializerError
at lwk.UniffiLib.<clinit>
at lwk.Network$Companion.mainnet
at com.blockstream.data.backend.lwk.LwkNetworkBackend.<init>
at com.blockstream.data.gdk.GdkSession.initNetworkBackends
at com.blockstream.data.gdk.GdkSession.connect
at com.blockstream.data.gdk.GdkSession.loginWithLoginCredentials
at com.blockstream.compose.models.login.LoginViewModel$loginWithPinOrMnemonic$1.invokeSuspend
...
Caused by: java.lang.RuntimeException: UniFFI API checksum mismatch: try cleaning and rebuilding your project
at lwk.IntegrityCheckingUniffiLib.uniffiCheckApiChecksums
at lwk.IntegrityCheckingUniffiLib.<clinit>
Full logcat
-------- 5805 5805 E AndroidRuntime: FATAL EXCEPTION: main
-------- 5805 5805 E AndroidRuntime: Process: com.greenaddress.greenbits_android_wallet, PID: 5805
-------- 5805 5805 E AndroidRuntime: java.lang.ExceptionInInitializerError
-------- 5805 5805 E AndroidRuntime: at lwk.UniffiLib.<clinit>(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:8)
-------- 5805 5805 E AndroidRuntime: at lwk.Network$Companion$mainnet$$inlined$uniffiRustCall$1.invoke(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:4)
-------- 5805 5805 E AndroidRuntime: at lwk.Network$Companion$mainnet$$inlined$uniffiRustCall$1.invoke(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:14)
-------- 5805 5805 E AndroidRuntime: at lwk.UniffiRustCallStatusHelper.withReference$lib(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:9)
-------- 5805 5805 E AndroidRuntime: at lwk.Network$Companion.mainnet(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:12)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.data.backend.lwk.LwkNetworkBackend.<init>(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:40)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.data.gdk.GdkSession.initNetworkBackends(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:220)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.data.gdk.GdkSession.connect(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:153)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.data.gdk.GdkSession.loginWithLoginCredentials(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:27)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.data.gdk.GdkSession.loginWithLoginCredentials$default(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:113)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.data.gdk.GdkSession.loginWithWallet(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:94)
-------- 5805 5805 E AndroidRuntime: at com.blockstream.compose.models.login.LoginViewModel$loginWithPinOrMnemonic$1.invokeSuspend(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:126)
-------- 5805 5805 E AndroidRuntime: at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:11)
-------- 5805 5805 E AndroidRuntime: at kotlinx.coroutines.DispatchedTask.run(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:127)
-------- 5805 5805 E AndroidRuntime: at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:1)
-------- 5805 5805 E AndroidRuntime: at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:62)
-------- 5805 5805 E AndroidRuntime: at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:29)
-------- 5805 5805 E AndroidRuntime: at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:1)
-------- 5805 5805 E AndroidRuntime: Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@7dbae6d, Dispatchers.Main.immediate]
-------- 5805 5805 E AndroidRuntime: Caused by: java.lang.RuntimeException: UniFFI API checksum mismatch: try cleaning and rebuilding your project
-------- 5805 5805 E AndroidRuntime: at ge.g(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:3)
-------- 5805 5805 E AndroidRuntime: at lwk.IntegrityCheckingUniffiLib.uniffiCheckApiChecksums(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:992)
-------- 5805 5805 E AndroidRuntime: at lwk.IntegrityCheckingUniffiLib.<clinit>(r8-map-id-eba37adec517341ce9f8432a2a824f7221e62e373e383229433fbb9433ed751f:22)
-------- 5805 5805 E AndroidRuntime: ... 18 more
Analysis
gradle/libs.versions.tomlpinsblockstream-lwk = "0.19.0".- LWK's Kotlin bindings are generated with gobley 0.3.7. It declares the
u16returns of theuniffi_lwk_checksum_*functions asShortwith JNA direct mapping. Rust zero-extends the value. ART's compiled JNI stubs on 32-bit ARM don't re-extend small return values, so after AOT compilation the checksum read on armeabi-v7a is wrong anduniffiCheckApiChecksumsthrows. arm64 is unaffected. - LWK fixed this by generating the bindings with a patched gobley (lwk@22659e7, upstream PR Read unsigned 8/16-bit direct-mapped returns as Int on JVM and Android gobley/gobley#297). The fix is not in 0.19.0 or 0.19.1.
- glsdk (Greenlight) uses the same generator and recently added the same workaround in
build/.tasks.yml. glsdk 0.3.0 may therefore also be affected on 32-bit ARM, for example in Lightning flows. - Ruled out: duplicate
liblwk.sohidden bypackaging.jniLibs.pickFirsts("**/*.so"). GDK 0.78.0 ships onlylibgreen_gdk_java.soand exports no UniFFI or LWK symbols. glsdk shipslibglsdk.
Suggested fix
- Bump LWK to the first release containing lwk@22659e7, and glsdk to a release built with the patched gobley.
- Possible interim mitigation:
android:vmSafeMode="true"in the manifest to prevent AOT compilation, at some performance cost. Droppingarmeabi-v7awould instead lock out existing 32-bit users.
Verified workaround
Resetting the app to non-AOT code may avoid the crash without touching wallet data:
adb shell cmd package compile -m verify -f com.greenaddress.greenbits_android_wallet
Background dexopt will likely re-compile the app later, bringing the crash back.
Activity
willpubissues commentedon Oct 19, 2026
Looks like its already in the pipeline to be fixed, but the workaround maybe useful for others like me
[-]UniFFI API checksum mismatch Crash on opening wallet on armeabi-v7a[/-][+]"UniFFI API checksum mismatch" in LWK bindings on armeabi-v7a[/+]ardier16 commentedon Oct 19, 2026
@willpubissues thanks for the detailed report and investigation! We’re aware of this crash and have already pushed a fix that will be available in the next release. We’ll let you know when it’s out.
It would be helpful if you could test the update on your Redmi A1 once it’s available and let us know whether it resolves the crash.
willpubissues commentedon Oct 19, 2026