Summary
Hard crash (native SIGABRT) when re-setting-up the blox that is already added and currently selected. Root cause is a Go nil-pointer dereference in the shared react-native-fula native client, caused by a concurrency race between the InitialSetup flow and the still-mounted Blox/MainTabs screen.
Repro
- App already set up with a blox (lands on
MainTabs).
- Home → Connect to WiFi → re-setup the currently-selected blox.
- On the Set Authorizer screen → app hard-crashes.
Root cause (from logcat)
ReactNativeJS: Error listActivePlugins: ... all dials failed # a c.bl.* read in flight
ReactNative: Previous Fula client shutdown successfully. # initFula's Shutdown ran
ReactNative: Creating a new Fula instance / Fula initialized # initFula's newClient ran
E Go: panic: runtime error: invalid memory address or nil pointer dereference
E Go: [signal SIGSEGV: segmentation violation code=0x1 addr=0xb8 ...]
F libc: Fatal signal 6 (SIGABRT) ... land.fx.blox
One shared native libp2p client ("fula"). InitialSetup and MainTabs are sibling routes, so navigating to setup leaves MainTabs/Blox.screen mounted and still polling (getBloxSpace → BloxFreeSpace, getFolderSize → GetFolderSize, checkBloxConnection, listActivePlugins). SetBloxAuthorizer.generateAppPeerId calls Helper.initFula on mount (logout + Shutdown + newClient), and the in-flight reads nil-deref the torn-down client.
Fix (this PR — box mitigation)
generateAppPeerId only needs the app's own peerId, which is deterministic from the DID keypair and already persisted as appPeerId. The subsequent auth exchange runs over BLE/HTTP (exchangeConfig / blePeerExchange), independent of the fula client. So reuse the stored appPeerId and skip initFula — extracted into the pure helper resolveAppPeerId(storedAppPeerId, initFn). In the repro path appPeerId is always present → no teardown → no race → no crash. Branch: fix/box-resetup-current-blox-crash.
⚠️ Mitigation, not a full fix
Keep open until go-fula#242 ships, the rebuilt aar is bundled, and the crash is verified gone on-device. A complementary broad mitigation (suspend Blox/MainTabs polling while an InitialSetup route is focused) is also planned.
Known limitation
resolveAppPeerId reuses the stored appPeerId whenever truthy. logout/reset/setWalletId(_, clearSigniture=true) clear it with the credentials, but setSigniture/setPassword do not — so an identity change via those setters without a full logout could reuse a stale id. Close that gap when the durable fix lands (clear appPeerId on credential change, or store + match an identity fingerprint).
Summary
Hard crash (native
SIGABRT) when re-setting-up the blox that is already added and currently selected. Root cause is a Go nil-pointer dereference in the sharedreact-native-fulanative client, caused by a concurrency race between the InitialSetup flow and the still-mountedBlox/MainTabsscreen.Repro
MainTabs).Root cause (from logcat)
One shared native libp2p client ("fula").
InitialSetupandMainTabsare sibling routes, so navigating to setup leavesMainTabs/Blox.screenmounted and still polling (getBloxSpace→BloxFreeSpace,getFolderSize→GetFolderSize,checkBloxConnection,listActivePlugins).SetBloxAuthorizer.generateAppPeerIdcallsHelper.initFulaon mount (logout + Shutdown + newClient), and the in-flight reads nil-deref the torn-down client.Fix (this PR — box mitigation)
generateAppPeerIdonly needs the app's own peerId, which is deterministic from the DID keypair and already persisted asappPeerId. The subsequent auth exchange runs over BLE/HTTP (exchangeConfig/blePeerExchange), independent of the fula client. So reuse the storedappPeerIdand skipinitFula— extracted into the pure helperresolveAppPeerId(storedAppPeerId, initFn). In the repro pathappPeerIdis always present → no teardown → no race → no crash. Branch:fix/box-resetup-current-blox-crash.initFula).fix/242-gate-blockchain-methods): gate allc.bl.*methods throughbeginOpsoShutdowndrains them and post-shutdown calls returnErrClientClosedinstead of nil-dereferencing.Keep open until go-fula#242 ships, the rebuilt aar is bundled, and the crash is verified gone on-device. A complementary broad mitigation (suspend
Blox/MainTabspolling while an InitialSetup route is focused) is also planned.Known limitation
resolveAppPeerIdreuses the storedappPeerIdwhenever truthy.logout/reset/setWalletId(_, clearSigniture=true)clear it with the credentials, butsetSigniture/setPassworddo not — so an identity change via those setters without a full logout could reuse a stale id. Close that gap when the durable fix lands (clearappPeerIdon credential change, or store + match an identity fingerprint).