Skip to content

fix(android): forward ExecuTorch consumer ProGuard rules#1325

Merged
msluszniak merged 1 commit into
software-mansion:mainfrom
injunchoi98:fix/android-consumer-proguard-rules
Jul 22, 2026
Merged

fix(android): forward ExecuTorch consumer ProGuard rules#1325
msluszniak merged 1 commit into
software-mansion:mainfrom
injunchoi98:fix/android-consumer-proguard-rules

Conversation

@injunchoi98

@injunchoi98 injunchoi98 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes an Android release crash caused by R8 removing ExecuTorch classes that are accessed during JNI initialization.

at minified release builds without the consumer rules, the app crashes during ETInstaller initialization:

java.lang.ClassNotFoundException: org.pytorch.executorch.Module
at java.lang.System.loadLibrary(...)
at com.swmansion.rnexecutorch.ETInstaller.<init>(...)

This PR ports the upstream rules and registers them through consumerProguardFiles

The first two rules ared covered with RN's own consumer rules, but are intentionally retained to keep the upstream ExecuTorch rule block intact. The rule that fixes the observed Module crash is:

-keepclasseswithmembers class org.pytorch.executorch.** {
    native <methods>;
}

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

  1. Enable R8/ProGuard for the release build.
  2. Build the minified release APK
  3. Verify that JNI-accessed classes retain their names in mapping.txt

Screenshots

Related issues

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

Additional notes

Android-only; iOS does not use R8. tested on a android physical device(galaxy s20 FE)

The upstream ExecuTorch rules are copied without semantic changes.

@msluszniak msluszniak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for contributing! The PR looks solid.

One blocking gap: the rules are scoped to org.pytorch.executorch.**, but RNE resolves its own class by literal descriptor from C++ (ETInstallerModule.h:18Lcom/swmansion/rnexecutorch/ETInstaller;). ETInstaller has @DoNotStrip on the method, not the class, so R8 can still rename the class — which is the failure shape your stack trace shows (ETInstaller.<init>). See the inline comment.

Also: could you paste the real logcat? System.loadLibrary doesn't throw ClassNotFoundException, and ETInstaller.init catches only UnsatisfiedLinkError, so the trace in the description doesn't match the diagnosis. Helps confirm which rule is load-bearing.

Comment thread packages/react-native-executorch/android/consumer-proguard-rules.pro Outdated
@injunchoi98
injunchoi98 force-pushed the fix/android-consumer-proguard-rules branch from f5a90a9 to 9573152 Compare July 22, 2026 04:01
@injunchoi98

Copy link
Copy Markdown
Contributor Author

Thank you very much for the thorough review and detailed explanations. I’ve applied the requested changes!

We’re using React Native ExecuTorch successfully in our app, so thank you as well for building and maintaining this library.

Here is the raw logcat from a minified release build without the consumer rules, reproduced on a physical Galaxy S20 FE:

07-22 12:51:50.508 20405 20679 D nativeloader: Load /data/app/~~IBCYjbXes9KZ7UOlbtmEmA==/com.earlyriser42.classic-2SuLRCS9eEf6EjiAWQzJyA==/base.apk!/lib/arm64-v8a/libexecutorch.so using class loader ns clns-4 (caller=/data/app/~~IBCYjbXes9KZ7UOlbtmEmA==/com.earlyriser42.classic-2SuLRCS9eEf6EjiAWQzJyA==/base.apk!classes4.dex): ok
07-22 12:51:50.544 20405 20679 E log     : error java.lang.ClassNotFoundException: org.pytorch.executorch.Module
07-22 12:51:50.544 20405 20679 E log     :      at java.lang.Runtime.nativeLoad(Native Method)
07-22 12:51:50.544 20405 20679 E log     :      at java.lang.Runtime.loadLibrary0(Runtime.java:1109)
07-22 12:51:50.544 20405 20679 E log     :      at java.lang.Runtime.loadLibrary0(Runtime.java:1033)
07-22 12:51:50.544 20405 20679 E log     :      at java.lang.System.loadLibrary(System.java:1765)
07-22 12:51:50.544 20405 20679 E log     :      at com.swmansion.rnexecutorch.ETInstaller.<init>(SourceFile:11)

--------- beginning of crash
07-22 12:51:50.550 20405 20680 E AndroidRuntime: FATAL EXCEPTION: mqt_v_native
07-22 12:51:50.550 20405 20680 E AndroidRuntime: Process: com.earlyriser42.classic, PID: 20405
07-22 12:51:50.550 20405 20680 E AndroidRuntime: com.facebook.react.common.JavascriptException: Error: Exception in HostObject::get for prop 'ETInstaller': java.lang.ClassNotFoundException: org.pytorch.executorch.Module

@msluszniak

Copy link
Copy Markdown
Member

Thanks for the logcat — it makes the mechanism clear. Worth noting for the record: System.loadLibrary can surface a ClassNotFoundException indirectly. Loading libexecutorch.so runs its JNI_OnLoad, which does FindClass("org/pytorch/executorch/Module"); when R8 has renamed Module, that lookup fails and the exception propagates up through nativeLoadloadLibrary. Since it's a ClassNotFoundException (not an UnsatisfiedLinkError), ETInstaller.init's catch doesn't swallow it, so it reaches JS as the fatal you saw. That confirms the load-bearing rule here is the upstream native <methods> keep pinning Module's name.

@msluszniak msluszniak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested the fix on minified build with our llm demo app, and the issue reproduced clearly. Without the fix, I got the same crash. After applying the fix, it worked correctly. Btw, can you disclose the name of the app you are working on? Our team is very curious to see how React Native ExecuTorch is used in apps :))

@msluszniak
msluszniak merged commit 189c24f into software-mansion:main Jul 22, 2026
10 checks passed
@injunchoi98

Copy link
Copy Markdown
Contributor Author

Thank you so much for reviewing and testing the fix! Sure thing — our app is Lita Book. We are using kokoro at book reader. it’s one of several projects I’m building with my teammates. We’re continuing to improve it and gradually grow the user base :)

@msluszniak

Copy link
Copy Markdown
Member

Thank you for your response, we'll look at Lita Book for sure :))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants