Skip to content

NullPointerException in FlutterSecureStorage.initialize() when Activity is paused - Android 13 #1084

@cloudsvcsupport

Description

@cloudsvcsupport

Human reviewed + Claude Sonnet drafted

flutter_secure_storage version: 10.0.0

Flutter version: 3.41.6

Platform: Android 13 (SDK 33)

Device: Samsung Galaxy A32 (SM-A325F)


Description

A fatal NullPointerException is thrown inside FlutterSecureStorage.initialize() when the plugin's MethodRunner executes on its background HandlerThread after the Activity has been paused.

The crash is unrecoverable and happens in production. It has been observed on multiple installs on the same device/OS combination.

Stacktrace

java.lang.NullPointerException
  at com.it_nomads.fluttersecurestorage.FlutterSecureStorage.initialize (FlutterSecureStorage.java:149)
  at com.it_nomads.fluttersecurestorage.FlutterSecureStoragePlugin$MethodRunner.run (FlutterSecureStoragePlugin.java:127)
  at android.os.Handler.handleCallback (Handler.java:942)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.os.HandlerThread.run (HandlerThread.java:67)

What happened

FlutterSecureStorage.initialize() is called lazily on the first storage operation. The plugin dispatches all operations via MethodRunner on a HandlerThread. When MainActivity is paused before the first storage call is made, the Activity context held by the plugin becomes null. The subsequent MethodRunner execution then crashes at line 149 of FlutterSecureStorage.java reading that null context.

Expected behavior

Either:

  • initialize() is called eagerly when the plugin binding is established (while the Activity context is guaranteed valid), or
  • MethodRunner null-checks the context before proceeding and surfaces a recoverable PlatformException with code INIT_FAILED instead of crashing

To reproduce

  1. Cold-start the app
  2. Immediately press Home or switch apps before the first FlutterSecureStorage read/write completes
  3. Return to the app or trigger a storage operation from a background callback

Additional context

  • The crash is fatal (UncaughtExceptionHandler) - not catchable from Dart
  • Only observed on Android; iOS unaffected
  • Using default AndroidOptions() (RSA OAEP + AES-GCM)
  • No WidgetsFlutterBinding.ensureInitialized() issue - the binding is initialized correctly

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions