react-native
react-native copied to clipboard
UIImplementation.createView "Root node with tag 21 doesn't exist " for both debug builds and prod builds
Description
If an apk is debug enabled, one out of 3 times, the first load on physical devices (Pixel 5, Samsung S20 Ultra, etc.) cause errors due to "no active CatalystInstance". RN error screen also shows "Root node with tag 21 doesn't exist". It only happens on the first load. Sub-sequential loads have no issue. [Update: we observed it is repeated issue on production!]
First error call stack:
Unhandled SoftException com.facebook.react.bridge.ReactNoCrashSoftException: No active CatalystInstance, cannot emitUpdateDimensionsEvent at com.facebook.react.modules.deviceinfo.DeviceInfoModule.emitUpdateDimensionsEvent(DeviceInfoModule.java:94) at com.facebook.react.ReactRootView$CustomGlobalLayoutListener.emitUpdateDimensionsEvent(ReactRootView.java:1075) at com.facebook.react.ReactRootView$CustomGlobalLayoutListener.checkForDeviceDimensionsChanges(ReactRootView.java:1032) at com.facebook.react.ReactRootView$CustomGlobalLayoutListener.onGlobalLayout(ReactRootView.java:916) at android.view.ViewTreeObserver.dispatchOnGlobalLayout(ViewTreeObserver.java:1084) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4302) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3116) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10885) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1301) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309) at android.view.Choreographer.doCallbacks(Choreographer.java:923) at android.view.Choreographer.doFrame(Choreographer.java:852) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283) 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.app.ActivityThread.main(ActivityThread.java:8762) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Second error call stack:
com.facebook.react.bridge.ReactNoCrashSoftException: Cannot get UIManager because the context doesn't contain an active CatalystInstance. at com.facebook.react.uimanager.UIManagerHelper.getUIManager(UIManagerHelper.java:77) at com.facebook.react.uimanager.UIManagerHelper.getEventDispatcher(UIManagerHelper.java:128) at com.facebook.react.uimanager.UIManagerHelper.getEventDispatcherForReactTag(UIManagerHelper.java:106) at com.th3rdwave.safeareacontext.SafeAreaProviderManagerKt.handleOnInsetsChange(SafeAreaProviderManager.kt:39) at com.th3rdwave.safeareacontext.SafeAreaProviderManagerKt.access$handleOnInsetsChange(SafeAreaProviderManager.kt:1) at com.th3rdwave.safeareacontext.SafeAreaProviderManager$addEventEmitters$1.invoke(SafeAreaProviderManager.kt:28) at com.th3rdwave.safeareacontext.SafeAreaProviderManager$addEventEmitters$1.invoke(SafeAreaProviderManager.kt:28) at com.th3rdwave.safeareacontext.SafeAreaProvider.maybeUpdateInsets(SafeAreaProvider.kt:21) at com.th3rdwave.safeareacontext.SafeAreaProvider.onPreDraw(SafeAreaProvider.kt:39) at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1121) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4442) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3116) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10885) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1301) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309) at android.view.Choreographer.doCallbacks(Choreographer.java:923) at android.view.Choreographer.doFrame(Choreographer.java:852) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283) 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.app.ActivityThread.main(ActivityThread.java:8762) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
React Native Version
0.72.6
Output of npx react-native info
System: OS: macOS 13.5.1 CPU: (10) arm64 Apple M1 Pro Memory: 78.66 MB / 16.00 GB Shell: version: 3.2.57 path: /bin/bash Binaries: Node: version: 18.18.2 path: /opt/homebrew/opt/node@18/bin/node Yarn: Not Found npm: version: 7.24.2 path: ???/node_modules/.bin/npm Watchman: version: 2023.07.10.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.12.1 path: /opt/homebrew/bin/pod SDKs: iOS SDK: Platforms: - DriverKit 22.1 - iOS 16.1 - macOS 13.0 - tvOS 16.1 - watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: Not Found Xcode: version: 14.1/14B47b path: /usr/bin/xcodebuild Languages: Java: version: 11.0.17 path: /Library/Java/JavaVirtualMachines/jdk-11.0.17+8/Contents/Home/bin/javac Ruby: version: 2.6.10 path: /usr/bin/ruby npmPackages: "@react-native-community/cli": Not Found react: installed: 18.2.0 wanted: 18.2.0 react-native: installed: 0.72.6 wanted: ^0.72.6 react-native-macos: Not Found npmGlobalPackages: "react-native": Not Found Android: hermesEnabled: false newArchEnabled: false iOS: hermesEnabled: true newArchEnabled: false
Steps to reproduce
- Build a debug apk with index.android.bundle
- Side load the apk to a Samsung S20 Ultra or Pixel 5
- Start the app
- Observe if an error screen shows up
- If no, delete the app and repeat step 2 to 4
Snack, screenshot, or link to a repository
:warning: | Newer Version of React Native is Available! |
---|---|
:information_source: | You are on a supported minor version, but it looks like there's a newer patch available - 0.72.7. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases. |
:warning: | Missing Reproducible Example |
---|---|
:information_source: | We could not detect a reproducible example in your issue report. Please provide either:
|
Side load the apk to a Samsung S20 Ultra or Pixel 5
Is this specific to those 2 modules only?
I'm having the same issue on pixel 6a emulator
Side load the apk to a Samsung S20 Ultra or Pixel 5
Is this specific to those 2 modules only?
We found the same issue on pixel 6 pro, pixel 2 xl, pixel 4a, and Samsung s21
I'm having the same problem, and I don't think it is a device issue. Did you find any solutions?
Side load the apk to a Samsung S20 Ultra or Pixel 5
Is this specific to those 2 modules only?
@cortinico We released our production build with RN 0.72.8. We found that 5% users got this crash with phased rollout. We also found a workaround to reduce the crash percentage to 0.15%. However, it is still too hight for us because our crash-free rate was about 99.95%. I guess the issue is coming from some race conditions could not being handled with RN Framework. It did not happen with RN 0.68. Here are some details. I can not reveal our source code. I am not sure if it necessary to create a separate project to reproduce this issue without my company's source code. Please let me know if you need more information.
- Our code is sophisticated. We are using brown field approach to build our app. The home page has a native ViewPager to render 5 tabs. The 1st, 2nd, and 4th are rendered by RN fragements, the 3rd and 5th are rendered in native fragments. We used to set offscreenPageLimit to 4 to keep these fragments in memory. There is no issues with RN 0.68 and ealier versions.
- The crash only happens 1~2 seconds after the app starts
- The work around we found is to delay loading other fragments. So, when the activity being created, we set offscreenPageLimit to 1. After 100ms, we set offscreenPageLimit to 4. With this tweak, we elimiated 97% crashes.
- In debug mode and by setting break points on UIImplementation.java. I did not find registerRootView has been invoked for node 21. How node tag is generated? In RN souce code, allocateTag never generate a tag with value 21.
Callstack: Caused by java.lang.AssertionError: Root node with tag 21 doesn't exist
at com.facebook.infer.annotation.Assertions.assertNotNull(Assertions.java:19)
at com.facebook.react.uimanager.UIImplementation.createView(UIImplementation.java:235)
at com.facebook.react.uimanager.UIManagerModule.createView(UIManagerModule.java:419)
at java.lang.reflect.Method.invoke(Method.java)
at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:188)
at com.facebook.jni.NativeRunnable.run(NativeRunnable.java)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:228)
at java.lang.Thread.run(Thread.java:1012)
Please let me know if you need more information.
We would need a reproducer as suggested by the bot
import static android.content.Context.VIBRATOR_SERVICE;
import android.app.Activity;
import android.app.PendingIntent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.Build;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.github.devnied.emvnfccard.enums.EmvCardScheme;
import com.github.devnied.emvnfccard.model.Application;
import com.github.devnied.emvnfccard.model.EmvCard;
import com.github.devnied.emvnfccard.parser.EmvTemplate;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
public class NativeModule extends ReactContextBaseJavaModule implements NfcAdapter.ReaderCallback {
/**
* Name of component so it can be accessed in JS
*/
public static final String REACT_CLASS = "NativeModule";
private Activity activity;
private NfcAdapter mNfcAdapter;
private Promise readNfcPromise;
NativeModule(ReactApplicationContext context) {
super(context);
activity = context.getCurrentActivity();
// For NFC reading
mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
}
@Override
public String getName() {
return REACT_CLASS;
}
@ReactMethod
public void readNfc(Promise promise) {
if(promise != null) {
if(readNfcPromise != null) {
promise.reject("Already reading", "Already reading");
return;
}
if (mNfcAdapter != null) {
this.readNfcPromise = promise;
Bundle options = new Bundle();
// Work around for some broken Nfc firmware implementations that poll the card too fast
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
// Enable ReaderMode for all types of card and disable platform sounds
// the option NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK is NOT set
// to get the data of the tag after reading
mNfcAdapter.enableReaderMode(this.activity,
this,
NfcAdapter.FLAG_READER_NFC_A |
NfcAdapter.FLAG_READER_NFC_B |
NfcAdapter.FLAG_READER_NFC_F |
NfcAdapter.FLAG_READER_NFC_V |
NfcAdapter.FLAG_READER_NFC_BARCODE |
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
options);
} else {
promise.reject("NFC reader not initialized", "NFC reader not initialized");
return;
}
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onTagDiscovered(Tag tag) {
}
}
I recently added NFC reading to my native module and I am getting this error now.
It's related to this line
mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
If I comment that line out I don't get the error, but then nothing works because I need that line :)
Please let me know if you need more information.
We would need a reproducer as suggested by the bot
I believe I found out why our app is carshing. We use the following code in our RN Fragment to update props when there are some data changes. If a such change occurs during the initialization of the RN App inside the RN Fragment, the error happens:
reactRootView?.appProperties = newProps
The only fix we can apply right now is to deplay the appProperties update. We will try to use DeviceEventEmitter to update data from Native to RN to see if we can remove the issue completely.
import static android.content.Context.VIBRATOR_SERVICE; import android.app.Activity; import android.app.PendingIntent; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.os.Build; import android.os.Bundle; import android.os.VibrationEffect; import android.os.Vibrator; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableMap; import com.github.devnied.emvnfccard.enums.EmvCardScheme; import com.github.devnied.emvnfccard.model.Application; import com.github.devnied.emvnfccard.model.EmvCard; import com.github.devnied.emvnfccard.parser.EmvTemplate; import java.io.IOException; import java.time.LocalDate; import java.time.ZoneId; import java.util.Date; import java.util.List; public class NativeModule extends ReactContextBaseJavaModule implements NfcAdapter.ReaderCallback { /** * Name of component so it can be accessed in JS */ public static final String REACT_CLASS = "NativeModule"; private Activity activity; private NfcAdapter mNfcAdapter; private Promise readNfcPromise; NativeModule(ReactApplicationContext context) { super(context); activity = context.getCurrentActivity(); // For NFC reading mNfcAdapter = NfcAdapter.getDefaultAdapter(context); } @Override public String getName() { return REACT_CLASS; } @ReactMethod public void readNfc(Promise promise) { if(promise != null) { if(readNfcPromise != null) { promise.reject("Already reading", "Already reading"); return; } if (mNfcAdapter != null) { this.readNfcPromise = promise; Bundle options = new Bundle(); // Work around for some broken Nfc firmware implementations that poll the card too fast options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250); // Enable ReaderMode for all types of card and disable platform sounds // the option NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK is NOT set // to get the data of the tag after reading mNfcAdapter.enableReaderMode(this.activity, this, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NFC_BARCODE | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS, options); } else { promise.reject("NFC reader not initialized", "NFC reader not initialized"); return; } } } @RequiresApi(api = Build.VERSION_CODES.O) @Override public void onTagDiscovered(Tag tag) { } }
I recently added NFC reading to my native module and I am getting this error now. It's related to this line
mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
If I comment that line out I don't get the error, but then nothing works because I need that line :) @tgreco Does NfcAdapter trigger any props update of your RN components? From my experience, props change causes this issue if the component is still loading/initialzing
The way I solved this was by moving mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
into a method that I would call from react-native along with using getReactApplicationContext()
instead of the context that was passed in the constructor.
Now it is working fine.
This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.
This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.
This issue was closed because it has been stalled for 7 days with no activity.