Skip to content

withSentryAndroidGradlePlugin.js imports @expo/config-plugins instead of the expo/config-plugins sub-export #6564

Description

@jlzlt

What React Native libraries do you use?

Expo Router

Are you using sentry.io or on-premise?

sentry.io (SaS)

Are you using any other error monitoring solution alongside Sentry?

No

Other Error Monitoring Solution Name

No response

@sentry/react-native SDK Version

7.11.0 (also confirmed in 8.21.0)

How does your development environment look like?

⬇  Place the `npx react-native@latest info` output here. ⬇

expo-env-info 2.1.0 environment info:
    System:
      OS: Windows 11 10.0.26200
    Binaries:
      Node: 20.19.6
      npm: 11.11.0
    IDEs:
      Android Studio: AI-253.29346.138.2531.14876573
    npmPackages:
      expo: ^57.0.10 => 57.0.10
      expo-router: ~57.0.10 => 57.0.10
      expo-updates: ~57.0.12 => 57.0.12
      react: 19.2.3 => 19.2.3
      react-dom: 19.2.3 => 19.2.3
      react-native: 0.86.2 => 0.86.2
      react-native-web: ^0.21.0 => 0.21.2
    Expo Workflow: managed (CNG — no ios/ or android/ committed)

Note: the bug was reproduced on Expo SDK 56 (react-native 0.85.3).
On SDK 57 the incorrect import resolves again by accident, because
@expo/config-plugins is hoisted to the project root.
Builds run on EAS Build (Linux for Android, macOS for iOS).

Sentry.init()

Sentry.init({
  dsn: "https://<redacted>@o<org>.ingest.us.sentry.io/<project>",

  // Keep dev sessions out of the production Sentry project.
  enabled: !__DEV__,

  sendDefaultPii: __DEV__,
  enableLogs: true,
});

Steps to Reproduce

  1. Create an Expo SDK 56 project using CNG (no committed ios/ or android/ folders).

  2. Install @sentry/react-native@7.11.0 and add the plugin to app.config.js:

    plugins: [["@sentry/react-native/expo", { organization: "...", project: "..." }]]

  3. Confirm @expo/config-plugins is NOT hoisted to the project root:

    npm ls @expo/config-plugins

    Under SDK 56 it resolves only to nested copies
    (expo/node_modules/, expo-sharing/node_modules/, expo-splash-screen/node_modules/).

  4. Run any command that evaluates config plugins:

    npx expo config --json --full


DETERMINISTIC CHECK (independent of hoisting)

The four plugin files disagree about which module to import:

grep -r "config-plugins" node_modules/@sentry/react-native/plugin/build/*.js

withSentry.js: require("expo/config-plugins")
withSentryAndroid.js: require("expo/config-plugins")
withSentryIOS.js: require("expo/config-plugins")
withSentryAndroidGradlePlugin.js: require("@expo/config-plugins") <-- inconsistent

@expo/config-plugins is not declared in @sentry/react-native's package.json as a
dependency, peer dependency, or optional dependency, so it resolves only when another
package happens to hoist it to the project root.

Confirmed identical in 7.11.0 and 8.21.0.

Expected Result

npx expo config --json --full evaluates the config plugins successfully.

withSentryAndroidGradlePlugin.js should import the expo/config-plugins sub-export,
matching its three sibling files, so it resolves through the expo package rather than
depending on @expo/config-plugins being hoisted to the project root.

Actual Result

npx expo config --json --full

Error: Cannot find module '@expo/config-plugins'
Require stack:

  • node_modules/@sentry/react-native/plugin/build/withSentryAndroidGradlePlugin.js
  • node_modules/@sentry/react-native/plugin/build/withSentry.js
  • node_modules/@sentry/react-native/plugin/build/index.js
  • node_modules/@sentry/react-native/expo.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1421:15)
    at Module._load (node:internal/modules/cjs/loader:1227:37)
    at Module.require (node:internal/modules/cjs/loader:1504:12)
    at Object. (withSentryAndroidGradlePlugin.js:4:26)

This breaks expo config, expo-doctor, and expo prebuild, so EAS builds fail
before any native compilation starts.

Notes:

  • withSentry.js requires this module eagerly at load time, so it fails even when
    experimental_android.enableAndroidGradlePlugin is not enabled.
  • This occurs before Sentry.init() runs — it is purely a build-time module resolution
    failure, unrelated to SDK configuration.
  • Workaround: declare @expo/config-plugins directly in the app's package.json.
    expo-doctor then warns that the package "should not be installed directly",
    so it trades one problem for another.
  • On SDK 57 the bug is masked again, because @expo/config-plugins is hoisted to the
    root by expo, expo-sharing and expo-splash-screen. The incorrect import is unchanged.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status
    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions