Skip to content

Expo plugin's apply from: line resolves @sentry/react-native from the directory Gradle was started in, not from the project #6828

Description

@jeffchen1981-fu

What React Native libraries do you use?

Expo (mobile only), Hermes, RN New Architecture

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

8.29.0 (also seen on 8.28.0)

How does your development environment look like?

System:
  OS: Windows 11 10.0.26300
Binaries:
  Node: 24.16.0
  npm: 11.16.0
Gradle: 9.3.1 (daemon JVM 17.0.18)
npmPackages:
  expo: 57.0.26
  react: 19.2.3
  react-native: 0.86.3
  @sentry/react-native: 8.29.0

(Trimmed from npx @react-native-community/cli info; the Gradle line is from ./gradlew --version. I have only measured this on Windows.)

Sentry.init()

// N/A: this is about the Expo config plugin's build.gradle output.
// The repro never runs the app.

Steps to Reproduce

  1. Create a fresh app and add the SDK:

    npx create-expo-app repro --template blank
    cd repro
    npm install @sentry/react-native@8.29.0
    

    Then add "@sentry/react-native" to plugins in app.json and run npx expo prebuild -p android.

  2. Look at android/app/build.gradle. Every node call that Expo/RN generate passes a working directory (.execute(null, rootDir), lines 12-15 and 20). The line the Sentry plugin adds does not:

    apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle.kts")
  3. Run Gradle from three different directories, always pointing at the same project with -p:

    # a) from the project's android/ dir
    cd repro/android && ./gradlew :app:tasks --all
    
    # b) from an empty directory
    cd /some/empty/dir && /path/to/repro/android/gradlew -p /path/to/repro/android :app:tasks --all
    
    # c) from a directory that has a different @sentry/react-native installed
    #    (here: an empty npm project with only @sentry/react-native@8.26.0)
    cd /some/other/dir && /path/to/repro/android/gradlew -p /path/to/repro/android :app:tasks --all
    

Expected Result

All three runs apply the project's own sentry.gradle.kts (8.29.0), because -p names the project. That is how every other node resolve in the generated file behaves. It is also how the SDK's own sample does this resolve: samples/react-native/android/app/build.gradle:6 uses .execute(null, rootDir).

Actual Result

run result
a) from android/ OK, task list contains generateSentryOptions (8.29.0)
b) from an empty dir BUILD FAILED: Could not read script '<project>\android\app\sentry.gradle.kts' as it does not exist.
c) from a dir with 8.26.0 BUILD SUCCESSFUL, but the 8.26.0 script was applied: the task list contains copySentryJsonConfiguration instead of generateSentryOptions. Nothing in the output says so.

.execute() with no arguments runs node in Gradle's current directory, which is wherever gradlew was invoked. So:

  • In (b) node cannot resolve the package, .text is empty (node's stderr is dropped), and Gradle reports a missing file under app/. The message does not point at the real cause.
  • In (c) node resolves whatever copy is reachable from that directory.

We hit (c) building one checkout from another (a git worktree QA build). The same can happen in a monorepo where CI runs gradlew -p apps/x/android from the repo root, if the copy reachable from the root is a different version.

Suggested fix: in packages/core/plugin/src/withSentryAndroid.ts, change resolveSentryReactNativePackageJsonPath to .execute(null, rootDir). I applied exactly that to build.gradle in the repro above, and both (b) and (c) then succeed with generateSentryOptions.

One related point: modifyAppBuildGradle returns early when the file already contains sentry.gradle.kts. So projects that already have the line, including bare projects with a committed android/, would not pick up the fix on their next prebuild unless the plugin also rewrites an existing bare line, the same way it already migrates sentry.gradle to sentry.gradle.kts.

(sentry-wizard's src/react-native/gradle.ts appears to emit the same bare .execute(). I haven't tested it, so I'm not including it here.)

Activity

  1. linear-code commented on Oct 3, 2026

    @linear-code
  2. self-assigned this
    on Oct 5, 2026
  3. alwx commented on Oct 5, 2026

    @alwx
    Contributor

    Thanks for reporting, @jeffchen1981-fu. We've seen your request and added it to our triage queue.

    We'll review it shortly and follow up if we need more information or once next steps are clearer.

  4. github-actions commented on Oct 8, 2026

    @github-actions
    Contributor

    A PR closing this issue has just been released 🚀

    This issue was referenced by PR #6840, which was included in the 8.30.0 release.

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

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions