GeezerVison is showing github.com — React Native in-memory storage fallback can never run · Issue #205 · exceptionless/Exceptionless.JavaScript
React Native in-memory storage fallback can never run #205
Description
ReactNativeExceptionlessClient.configureStorage in @exceptionless/react-native 3.2.1 wraps storage setup in a try/catch that is meant to fall back to in-memory storage when AsyncStorage is unavailable. Nothing inside the try can throw, and the real failure happens earlier, when the module is imported, so the fallback is dead code.
Where
What happens
- If the AsyncStorage native module isn't linked (for example,
pod install wasn't run or the app wasn't rebuilt), @react-native-async-storage/async-storage throws [@RNC/AsyncStorage]: NativeModule: AsyncStorage is null at module evaluation time (src/AsyncStorage.native.ts, line 22, in 2.2.0). Importing @exceptionless/react-native throws before startup() runs, so the app fails instead of falling back.
- If storage calls fail later, the
AsyncStorageProvider methods return rejected promises from inside the queue. The catch in configureStorage is never involved.
- The log message "AsyncStorage provider failed to initialize. Using in-memory storage." is never written.
Expected
If AsyncStorage can't be loaded or used, the client logs the message and keeps working with the default in-memory storage and usePersistedQueueStorage = false, as the catch intends.
Steps to reproduce
- Install
@exceptionless/react-native 3.2.1 and @react-native-async-storage/async-storage in a bare React Native iOS app, but skip pod install (or run a build that doesn't include the AsyncStorage native module).
- Import
Exceptionless from @exceptionless/react-native and call startup.
- The app throws
NativeModule: AsyncStorage is null while importing the package. The fallback message is never logged.
Suggested fix
Load AsyncStorage lazily inside the guarded path, for example await import("@react-native-async-storage/async-storage") (or a require) in configureStorage, made async and awaited from startup. Then verify it works with an awaited call such as getAllKeys() before setting usePersistedQueueStorage = true. If the fallback is supported, mark the peer dependency optional in peerDependenciesMeta. Otherwise, remove the try/catch and the message.
Activity
dave-otf commented on Oct 30, 2026
One edge case worth covering alongside the missing-native-module case: lazy import moves the import-time failure into the try/catch, but a storage method can still reject later. If the intended contract is “fall back whenever persistence is unavailable,” await a small probe such as getAllKeys() inside the guarded setup before enabling usePersistedQueueStorage, and test both a module-load throw and a rejected probe. If only a missing native module should fall back, making the peer dependency optional would make that narrower contract clear.
Metadata
Metadata
Development
No branches or pull requestsIssue actions