Skip to content

[Android] Misleading message when loadLibrary throws UnsatisfiedLinkError with app bundle #168272

@Sameri11

Description

@Sameri11

Steps to reproduce

Description

When an app is published as an Android App Bundle, errors occasionally occur during native-library loading (see #151638 (comment), #151638 (comment) and related comments).

The primary problem resides in this code block, which builds a human-readable error message:

throw new UnsupportedOperationException(
"Could not load libflutter.so this is possibly because the application"
+ " is running on an architecture that Flutter Android does not support (e.g. x86)"
+ " see https://docs.flutter.dev/deployment/android#what-are-the-supported-target-architectures"
+ " for more detail.\n"
+ "App is using cpu architecture: "
+ cpuArch
+ ", and the native libraries directory (with path "
+ nativeLibsDir.getAbsolutePath()
+ ") "
+ (nativeLibsDir.exists()
? "contains the following files: "
+ Arrays.toString(nativeLibsContents)
: "does not exist."),
unsatisfiedLinkError);
}

When running from a bundle, this log often shows:

App is using cpu architecture: aarch64, and the native libraries directory (with path /data/app/~~2UHRMKRY95HcmDUp4LaWNw==/za.co.clock.africlock-rUsnC1k6b87NW4W_Hk48kg==/lib/arm64) contains the following files: null

In fact, bundles can split native libraries across multiple directories. If you install the APKs generated by Bundletool (without ⁠useLegacyPackaging), the needed library may be in a different “split” directory.

Current Lookup Logic

The Flutter embedding lists native-library directories using only

File nativeLibsDir = new File(flutterApplicationInfo.nativeLibraryDir);

This is insufficient to enumerate every possible library location.

Possible fix

When building bundle and installing apk created out of this bundle with bundletool there is line in logs which describes path where native libs might be stored on device:

Configuring clns-7 for other apk /data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.en.apk:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.xxhdpi.apk. target_sdk_version=35, uses_libraries=, library_path=/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/lib/arm64:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.en.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg=

library_path is constructed from each split of app. Later, the loader logs exactly from which split it loads ⁠libflutter.so:

Load /data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk!/lib/arm64-v8a/libflutter.so using ns clns-7 from class loader (caller=/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk): ok

split_config.arm64_v8a.apk is the third dir in the path.

Main proposal here is to use not only nativeLibraryDir, but also all splitSourceDirs and construct paths where libraries might exist from them.

This change will produce a clear, comprehensive list of all inspected directories/APKs, making it easier to diagnose why a particular native library failed to load on split-APK installations.
Maybe it'll even help with investigation on #151638

Expected results

Correct UnsupportedOperationException with full list of possible locations of native libraries and its content.

Actual results

Only single base nativeLibsDir is listed which leads to null instead of list with available libraries.

Code sample

I created a simple project here: https://github.com/Sameri11/misleading_jni_libs_error
In the MainActivity.kt there is code which tries to construct library_paths from splitSourceDirs and print to log. This constructed path is the same as the path reported from native loader.

Make sure that project is built with flutter build appbundle and installed with bundletool. Detailed description is in Readme.

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs

4 lines
First and second are from native loader itself.
Third and fourth lines are from MainActivity.kt. Third line reports contents of nativeLibsDir alone.
Fourth line reports result of the code which compiles path from nativeLibsDir and splitSourceDirs.

2025-05-03 20:19:40.770 29789-29789 nativeloader            com.example.app_test                 D  Configuring clns-7 for other apk /data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.en.apk:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.xxhdpi.apk. target_sdk_version=35, uses_libraries=, library_path=/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/lib/arm64:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.en.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg=
2025-05-03 20:19:40.862 29789-29808 nativeloader            com.example.app_test                 D  Load /data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk!/lib/arm64-v8a/libflutter.so using ns clns-7 from class loader (caller=/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk): ok
2025-05-03 20:19:41.439 29789-29789 nativeloader            com.example.app_test                 D  Native Library Path: /data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/lib/arm64
2025-05-03 20:19:41.453 29789-29789 nativeLoader            com.example.app_test                 D  Load library path: /data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/lib/arm64:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/base.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.arm64_v8a.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.en.apk!/lib/arm64-v8a:/data/app/~~9xW4-yMGyelaPI4JoU8LUg==/com.example.app_test-TLMiWr6lcykuU_hY70C7mg==/split_config.xxhdpi.apk!/lib/arm64-v8a

Flutter Doctor output

Doctor output
flutter doctor -v
[✓] Flutter (Channel master, 3.32.0-1.0.pre.397, on macOS 14.7 23H124 darwin-arm64, locale en-RU) [5.2s]
    • Flutter version 3.32.0-1.0.pre.397 on channel master at /Users/<user>/projects/flutter
    • Upstream repository [email protected]:flutter/flutter.git
    • Framework revision c36748ff48 (10 hours ago), 2025-05-03 03:42:30 -0400
    • Engine revision c36748ff48
    • Dart version 3.9.0 (build 3.9.0-76.0.dev)
    • DevTools version 2.46.0-dev.0

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.2s]
    • Android SDK at /Users/samer/Library/Android/sdk
    • Emulator version 35.5.8.0 (build_id 13181580) (CL:N/A)
    • Platform android-35, build-tools 35.0.0
    • Java binary at: /Users/<user>/Applications/Android Studio Meerkat Feature Drop 2024.3.2 Canary 4.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.2) [2.1s]
    • Xcode at /Applications/Xcode-15.2.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [48ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2024.3.2) [47ms]
    • Android Studio at /Users/<user>/Applications/Android Studio Meerkat Feature Drop 2024.3.2 Canary 4.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)

[✓] Android Studio (version 2024.3) [46ms]
    • Android Studio at /Users/<user>/Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)

[✓] IntelliJ IDEA Ultimate Edition (version 2024.3.3) [46ms]
    • IntelliJ at /Users/samer/Applications/IntelliJ IDEA Ultimate.app
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin version 243.23654.44

[✓] VS Code (version 1.99.3) [12ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.108.0

[✓] Connected device (6 available) [7.1s]
......

[✓] Network resources [915ms]
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: buildBuilding flutter applications with the toolfound in release: 3.29Found to occur in 3.29found in release: 3.32Found to occur in 3.32has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-androidOwned by Android platform teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-androidTriaged by Android platform team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions