realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.79k stars 577 forks source link

Realm not bundled with EAS on development builds #5276

Closed thecoorum closed 1 year ago

thecoorum commented 1 year ago

How frequently does the bug occur?

Always

Description

While the build itself is completing successfully, while trying to run the app on the simulator it returns an error like

Error: Your JavaScript code tried to access a native module, Realm, that doesn't exist in this development build.
Make sure you are using the newest available development build of this app and running a compatible version of your JavaScript code. If you've installed a new library recently, you may need to make a new development build.
See https://expo.fyi/missing-native-module for more info, including how to disable these errors., js engine: hermes

Stacktrace & log output

ERROR  Error: Your JavaScript code tried to access a native module, Realm, that doesn't exist in this development build.
Make sure you are using the newest available development build of this app and running a compatible version of your JavaScript code. If you've installed a new library recently, you may need to make a new development build.
See https://expo.fyi/missing-native-module for more info, including how to disable these errors., js engine: hermes
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Registered callable JavaScript modules (n = 11): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, JSDevSupportModule, HMRClient, RCTEventEmitter.
        A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Registered callable JavaScript modules (n = 11): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, JSDevSupportModule, HMRClient, RCTEventEmitter.
        A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes

Can you reproduce the bug?

Always

Reproduction Steps

  1. Build the app with EAS and the following eas.config
"build": {
  "development": {
    "developmentClient": true,
    "distribution": "internal",
    "ios": {
      "simulator": true
    },
    "android": {
      "buildType": "apk"
    },
    "autoIncrement": true,
    "channel": "development"
  }
}

Version

11.3.1

What services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

Android API 33

Build environment

No response

Cocoapods version

No response

takameyer commented 1 year ago

@thecoorum Are you using expo-dev-client? This is required in order to use Realm with Expo. Reference: creating development builds

thecoorum commented 1 year ago

Hey @takameyer! Yep, I'm using expo-dev-client in my app and as you can see from eas config developmentClient option is also set to true

takameyer commented 1 year ago

@thecoorum Ah yeah, there it is. Overlooked that on first glance. What build command are you using?

thecoorum commented 1 year ago

@takameyer eas build --platform android --profile development

I'll share my whole eas.json maybe this will be also helpfull

{
  "cli": {
    "version": ">= 0.55.1",
    "appVersionSource": "remote"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": {
        "simulator": true
      },
      "android": {
        "buildType": "apk"
      },
      "autoIncrement": true,
      "channel": "development"
    },
    "production": {
      "channel": "release",
      "autoIncrement": true
    }
  },
  "submit": {
    "release": {}
  }
}
takameyer commented 1 year ago

@thecoorum Thanks for that. I'll have to try this out and see if I hit any snags. I have tested this before, but perhaps we are hitting some sort of regression.

thecoorum commented 1 year ago

@takameyer thanks a lot!

takameyer commented 1 year ago

@thecoorum I got it to work with a very minimal eas.json:

{
  "cli": {
    "version": ">= 3.3.2"
  },
  "build": {
    "development": {
      "distribution": "internal",
      "developmentClient": true,
      "android": {
        "gradleCommand": ":app:assembleDebug"
      },
      "ios": {
        "buildConfiguration": "Debug"
      }
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {}
  },
  "submit": {
    "production": {}
  }
}

Here is my package.json:

{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "expo start --dev-client",
    "android": "expo run:android",
    "ios": "expo run:ios"
  },
  "dependencies": {
    "@realm/react": "^0.4.1",
    "expo": "~47.0.12",
    "expo-dev-client": "~2.0.0",
    "expo-splash-screen": "~0.17.5",
    "expo-status-bar": "~1.4.2",
    "react": "18.1.0",
    "react-native": "0.70.5",
    "react-native-get-random-values": "~1.8.0",
    "realm": "^11.3.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/plugin-proposal-decorators": "^7.19.0",
    "@realm/babel-plugin": "^0.1.1",
    "@types/react": "~18.0.14",
    "@types/react-native": "~0.70.6",
    "typescript": "~4.3.5"
  },
  "private": true
}

Let me know if this helps!

thecoorum commented 1 year ago

@takameyer tried to re-build with appended "gradleCommand": ":app:assembleDebug", but no success. While inspecting the EAS logs I see that some gradlew tasks prefixed with :realm:* have NO-SOURCE after the task name. Can this be an issue?

takameyer commented 1 year ago

@thecoorum That seems odd. If you want to compare with the project I did this with, you can invoke the following command:

npx create-expo-app --template @realm/expo-template-ts

Does that project work?

thecoorum commented 1 year ago

@takameyer I was not even able to create an app with the provided template 🥲

Error: ENOENT: no such file or directory, open '/var/folders/nx/dwd680xs14d4k9qwpjbyts600000gp/T/.create-expo-app/template-cache/@realm/expo-template-ts-0.4.2.tgz'
takameyer commented 1 year ago

@thecoorum That is also odd. Can you make one with the Expo default template?

npx create-expo-app my-app
thecoorum commented 1 year ago

@takameyer just to clarify, do you want me to install realm into bare expo project and try to build it with EAS?

takameyer commented 1 year ago

@thecoorum In regards to this error:

Error: ENOENT: no such file or directory, open '/var/folders/nx/dwd680xs14d4k9qwpjbyts600000gp/T/.create-expo-app/template-cache/@realm/expo-template-ts-0.4.2.tgz'

This seems for me to be an independent from Realm. I just wanted to verify that any Expo template was functioning on your system.

But let's get back to the point. In any case, in your current project, it seems EAS is having difficulty finding Realm. My only guess is that something within the eas.json is causing this. Can you try and change the cli section to match the eas.json that I posted earlier?

  "cli": {
    "version": ">= 3.3.2"
  },

As this is 3 major versions ahead of yours, perhaps this has some sort of influence on linking your project with third party libraries.

thecoorum commented 1 year ago

@takameyer unfortunately, updating CLI version didn't help me and I'm unable to to install both of the realm templates with expo. I will try to bootstrap bare expo template and install just realm-js and @realm/react to test build on EAS

kneth commented 1 year ago

@thecoorum We leave the issue open, and you can post an update when you are ready.

thecoorum commented 1 year ago

@kneth @takameyer I bootstraped expo bare js template (https://github.com/thecoorum/realm-android-issue) and installed the latest realm and @realm/react. Now the issue is different

 ERROR  Error: Exception in HostObject::get(propName:Realm): java.lang.UnsatisfiedLinkError: couldn't find DSO to load: librealm.so caused by: dlopen failed: cannot locate symbol "__emutls_get_address" referenced by "/data/app/~~fsxFMLcUg3NvA2Dp-OUX3Q==/com.thecoorum.realmandroidissue-h-nQIjmZawsa93b_qshZ2A==/lib/arm64/librealm.so"... result: 0
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Registered callable JavaScript modules (n = 11): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, JSDevSupportModule, HMRClient, RCTEventEmitter.
        A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Registered callable JavaScript modules (n = 11): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, JSDevSupportModule, HMRClient, RCTEventEmitter.
        A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.
takameyer commented 1 year ago

@thecoorum try pinning the realm version to 11.3.1. The latest depends on RN 0.71.0 so it wont work with Expo

thecoorum commented 1 year ago

@takameyer can confirm that clean project runs realm successfuly. Will try to clean cache on expo and build again, else don't have a clue why realm can be not compiled

thecoorum commented 1 year ago

Clearing cache doesn't resolve an issue, still can see the same error. I also have a react-native.config.js that excludes some of the libraries on different platforms, but realm is not listed there

module.exports = {
  dependencies: {
    'react-native-ios-context-menu': {
      platforms: {
        // Disable library for Android
        android: null
      }
    },
    '@react-native-menu/menu': {
      platforms: {
        // Disable library for iOS
        ios: null
      }
    }
  }
}
takameyer commented 1 year ago

Hmm...can you share your package.json as well? I assume you haven't made any modifications to any android configuration files, or? And is ios working fine?

thecoorum commented 1 year ago

I assume you haven't made any modifications to any android configuration files, or?

Nope, I have fully managed expo project without any native folders

And is ios working fine?

Yeah, everything works as expected


Sure, here is the package.json

{
  "name": "solde",
  "version": "0.8.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "npx expo start --dev-client",
    "android": "npx expo start --android",
    "ios": "npx expo start --ios",
    "build:all": "eas build --resource-class m1-experimental",
    "build:ios": "eas build --platform ios --resource-class m1-experimental",
    "build:android": "eas build --platform android",
    "deploy:all": "eas submit",
    "deploy:ios": "eas build --platform ios --resource-class m1-experimental --auto-submit",
    "deploy:android": "eas submit -p android",
    "lint": "yarn rome check ./src/",
    "postinstall": "patch-package"
  },
  "dependencies": {
    "@gorhom/bottom-sheet": "^4.4.3",
    "@gorhom/portal": "^1.0.14",
    "@hookform/resolvers": "^2.9.7",
    "@legendapp/state": "^0.20.5",
    "@logrocket/react-native": "^1.7.2",
    "@react-native-community/datetimepicker": "6.5.2",
    "@react-native-menu/menu": "^0.7.2",
    "@react-navigation/bottom-tabs": "^6.5.2",
    "@react-navigation/native": "^6.0.12",
    "@react-navigation/native-stack": "^6.8.0",
    "@realm/react": "^0.4.1",
    "@sentry/react-native": "4.9.0",
    "@shopify/flash-list": "1.3.1",
    "@th3rdwave/react-navigation-bottom-sheet": "^0.2.2",
    "burnt": "^0.8.1",
    "date-fns": "^2.29.2",
    "dripsy": "^3.6.0",
    "expo": "^47.0.0-beta.7",
    "expo-application": "~5.0.1",
    "expo-blur": "~12.0.1",
    "expo-build-properties": "~0.4.1",
    "expo-constants": "~14.0.2",
    "expo-contacts": "~11.0.1",
    "expo-crypto": "~12.0.0",
    "expo-dev-client": "~2.0.1",
    "expo-device": "~5.0.0",
    "expo-file-system": "~15.1.1",
    "expo-font": "~11.0.1",
    "expo-haptics": "~12.0.1",
    "expo-linear-gradient": "~12.0.1",
    "expo-linking": "~3.3.0",
    "expo-localization": "~14.0.0",
    "expo-splash-screen": "~0.17.5",
    "expo-status-bar": "~1.4.2",
    "expo-system-ui": "~2.0.1",
    "expo-updates": "~0.15.6",
    "moti": "^0.20.0",
    "patch-package": "^6.5.0",
    "prop-types": "^15.8.1",
    "radash": "^10.3.2",
    "ramda": "^0.28.0",
    "react": "18.1.0",
    "react-hook-form": "^7.34.2",
    "react-native": "0.70.5",
    "react-native-date-picker": "^4.2.6",
    "react-native-draggable-flatlist": "^4.0.0",
    "react-native-gesture-handler": "~2.8.0",
    "react-native-get-random-values": "~1.8.0",
    "react-native-ios-context-menu": "^1.15.1",
    "react-native-mask-input": "^1.2.2",
    "react-native-reanimated": "~2.12.0",
    "react-native-safe-area-context": "4.4.1",
    "react-native-screens": "~3.18.0",
    "react-native-svg": "13.4.0",
    "react-native-ticker": "^5.1.0",
    "realm": "^11.3.1",
    "rome": "^10.0.1",
    "sentry-expo": "~6.0.0",
    "yup": "^0.32.11",
    "zeego": "^1.0.2"
  },
  "devDependencies": {
    "@babel/core": "^7.19.3",
    "babel-plugin-module-resolver": "^4.1.0"
  },
  "private": true
}
thecoorum commented 1 year ago

The only thing that I remembered is that there was an issue with crashing on expo and realm some time ago, so somebody advised to patch expo-modules-core. Could it be that this caused an issues with realm on android?

Here is the patch

diff --git a/node_modules/expo-modules-core/ios/Swift/ExpoBridgeModule.swift b/node_modules/expo-modules-core/ios/Swift/ExpoBridgeModule.swift
index 8132c0b..34a0b83 100644
--- a/node_modules/expo-modules-core/ios/Swift/ExpoBridgeModule.swift
+++ b/node_modules/expo-modules-core/ios/Swift/ExpoBridgeModule.swift
@@ -22,12 +22,6 @@ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
   override init() {
     appContext = AppContext()
     super.init()
-
-    // Listen to React Native notifications posted just before the JS is executed.
-    NotificationCenter.default.addObserver(self,
-                                           selector: #selector(javaScriptWillStartExecutingNotification(_:)),
-                                           name: NSNotification.Name.RCTJavaScriptWillStartExecuting,
-                                           object: nil)
   }

   deinit {
@@ -47,6 +41,12 @@ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
   public var bridge: RCTBridge! {
     didSet {
       appContext.reactBridge = bridge
+      bridge.dispatchBlock({ [weak self] in
+        guard let self = self, let bridge = self.appContext.reactBridge else {
+          return
+        }
+        self.appContext.runtime = EXJavaScriptRuntimeManager.runtime(fromBridge: bridge)
+      }, queue: RCTJSThread)
     }
   }

@@ -64,16 +64,4 @@ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
     appContext.useModulesProvider("ExpoModulesProvider")
     appContext.moduleRegistry.register(moduleType: NativeModulesProxyModule.self)
   }
-
-  // MARK: - Notifications
-
-  @objc
-  public func javaScriptWillStartExecutingNotification(_ notification: Notification) {
-    if (notification.object as? RCTBridge)?.batched == bridge {
-      // The JavaScript bundle will start executing in a moment,
-      // so the runtime is already initialized and we can get it from the bridge.
-      // This should automatically install the ExpoModules host object.
-      appContext.runtime = EXJavaScriptRuntimeManager.runtime(fromBridge: bridge)
-    }
-  }
 }
takameyer commented 1 year ago

@thecoorum Those are all swift files, so that wouldn't effect android.

takameyer commented 1 year ago

Can you pin realm to 11.3.1 in your current project by removing ^?

thecoorum commented 1 year ago

@takameyer forced realm version to 11.3.1, built with clear cached and cleared the bundler cache, still the same error

takameyer commented 1 year ago

@thecoorum I'm out of ideas. I'll reach out to Expo and see if they can see what the problem is. I think the amount of information provided should be enough to help provide visibility on your environment.

byCedric commented 1 year ago

Hey @thecoorum! Can you share a repository, with the basics that would reproduce this error on EAS? E.g.

That would help us figure out whats going on.

thecoorum commented 1 year ago

Hey @byCedric! As I mentioned here the bare expo app template with realm@11.3.1 and @realm/react are working good on Android simulator. Hovewer, I didn't apply any patches there, but as @takameyer mentioned they are all Swift related and should not affect the Android, so I'm kinda stuck what's going wrong. I'll open an issue in expo repo, maybe somebody from there knows the source of the issue

thecoorum commented 1 year ago

@takameyer @byCedric @kneth upgrading the expo resolved an issue. Thank you guys for you massive support!