Custom Expo module works in dev build, but cannot be imported into EAS build and crashes.

Hello!

Here’s my setup:

  • eas-cli/3.16.0 win32-x64 node-v16.13.0
  • Expo managed workflow
  • Rreact-Native 0.70.8

I’ve made a custom module (Expo Modules API) which provides functionality to create Android home screen shortcuts. When I build the app in dev mode and run it with the dev server (with command “expo run:android”), it works perfectly — I’m able to create home screen shortcuts on my phone. However, when I create an EAS APK-file build (with command “eas build -p android --profile preview”), pressing the shortcut creation button crashes the app. According to the logs (below), this happens because the custom module cannot be imported.

Here’s the function that, when invoked, leads to a crash:

const createDynamicShortcut = async (shortcutId: string, shortLabel: string, deepLink: string) => {

    if (isExpoGo() !== true) {

      const longLabel = 'This is a dynamic shortcut'
      const targetClass = 'expo.modules.devlauncher.launcher.DevLauncherActivity'
      const iconName = 'splashscreen_image'

      try {
        const { createPinnedShortcut } = await import('../../modules/home-screen-shortcut')
        await createPinnedShortcut(shortcutId, shortLabel, longLabel, targetClass, iconName, deepLink)
      } catch (error) {
        console.error('Failed to create dynamic shortcut:', error)
      }
    } else {
      console.log('expoGO is active - no custom modules allowed')
    }
  }

I’ve tried:

  • import module not dynamically, but with: “import { createPinnedShortcut } from ‘…/…/modules/home-screen-shortcut’”
  • import module with modified metro.cofig.js with: “import { createPinnedShortcut } from ‘home-screen-shortcut’”
  • modify app.json to add custom module as dependency “dependencies”: {
    “expo-home-screen-shortcut”: “~11.0.0”
    }
  • checking with ChatGPT / GglBard :slight_smile:

Here’s crash log:

07-23 12:12:36.464 20599 20640 E ReactNativeJS: Error: Cannot find native module 'HomeScreenShortcut'
07-23 12:12:36.468 20599 20640 E ReactNativeJS: 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.
07-23 12:12:36.468 20599 20640 E ReactNativeJS:         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.
07-23 12:12:36.470 20599 20641 E AndroidRuntime: FATAL EXCEPTION: mqt_native_modules
07-23 12:12:36.470 20599 20641 E AndroidRuntime: Process: com.eggbro.startable, PID: 20599
07-23 12:12:36.470 20599 20641 E AndroidRuntime: com.facebook.react.common.JavascriptException: Error: Cannot find native module 'HomeScreenShortcut', stack:
07-23 12:12:36.470 20599 20641 E AndroidRuntime: <unknown>@401:291
07-23 12:12:36.470 20599 20641 E AndroidRuntime:
07-23 12:12:36.470 20599 20641 E AndroidRuntime:        at com.facebook.react.modules.core.ExceptionsManagerModule.reportException(ExceptionsManagerModule.java:72)
07-23 12:12:36.470 20599 20641 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)

Please let me know if you have ideas, how to fix this issue. Thank you!

I am having the exact same issue. Did you ever figure out a solution? I’ve been banging my head on my desk for days … I have no clue what is going wrong. If I do “yarn expo run:android” everything works just fine. If I do “eas build --local -e development -p android” the build says it can’t load the module.

I created a brand new expo react app and added a -local module in there, and it works just fine. I even created a brand new module in my app and it also fails in the exact same way, so it is clearly something with my project setup.

Interestingly, if I put a syntax error into the module code, the local dev build will fail, but the eas builds (both local and submitted) will “succeed”, so I don’t think there is anything wrong with the modules, the eas build system just isn’t building them, and I have no idea why.

This is my eas.json file … any thoughts?

{
    "cli": {
        "version": ">= 3.14.0",
        "promptToConfigurePushNotifications": false,
        "appVersionSource": "local"
    },
    "build": {
        "development": {
            "developmentClient": true,
            "distribution": "internal",
            "android": {
                "gradleCommand": ":app:assembleDebug"
            },
            "ios": {
                "buildConfiguration": "Debug"
            }
        },
        "preview": {
            "distribution": "internal"
        },
        "production": {
            "autoIncrement": true // auto-increment build number
        }
    },
    "submit": {
        "production": {}
    }
}

Hi, there is no solution on my end yet :slightly_frowning_face:. I will post back if I find something. Please let me know if you find a solution.

Uh, yeah, mine was rather embarrassing. I was tired of getting conflicts in the ios folder when I checked in my project, so I added this to my .gitignore in the root of my project a little while back:

ios/
android/

As it turns out, when the eas build gathers your project, compresses it and sends it to the build folder (or server), it applies the .gitignore throughout all of your project directories, so this caused it to ignore these folders:

modules/MyModule/ios/...
modules/MyModule/android/...

So as far as the build was concerned, I was giving it a module with no native code.

This page has some helpful commands to let you see what exactly the build is using to build your project. I inspected those and realized those folders were empty and then worked backwards.

I updated my .gitignore to this and all is well:

/ios
/android

Wow, it works! Thank you very much!!!

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.