Skip to content

Android build script never reads ndkVersion, so AGP downloads its default NDK alongside the host app's pin #6702

Description

@MHarris-SgyMd

What React Native libraries do you use?

Expo (mobile only), RN New Architecture, Hermes

Are you using sentry.io or on-premise?

sentry.io (SaS)

Are you using any other error monitoring solution alongside Sentry?

No

@sentry/react-native SDK Version

8.24.0 (the relevant file is unchanged on main as of 8.26.0)

How does your development environment look like?

React Native 0.86.3, Expo SDK 57, Android Gradle Plugin 8.12.0 (from React Native's gradle/libs.versions.toml), newArchEnabled=true, hermesEnabled=true.
Host root build.gradle pins rootProject.ext.ndkVersion = "27.1.12297006" (the React Native 0.86 catalog value) ahead of `apply plugin: "expo-root-project"`.
Android SDK on CI: ubuntu GitHub-hosted runner, only NDK 27.1.12297006 installed by our bootstrap before Gradle runs.

Sentry.init()

Sentry.init({
  dsn: 'https://...@sentry.io/...',
  // Nothing here matters for this report: it is a Gradle configuration
  // issue in packages/core/android/build.gradle, independent of runtime options.
});

Steps to Reproduce

  1. In a React Native 0.86 / Expo 57 app with the New Architecture enabled, pin the NDK in the root android/build.gradle (the React Native template form or Expo's expo-root-project plugin both end up with rootProject.ext.ndkVersion):

    ext {
      ndkVersion = "27.1.12297006"
    }
  2. Make sure only that NDK is installed under $ANDROID_HOME/ndk.

  3. Run any Gradle evaluation, for example ./gradlew :app:help.

Expected Result

Every native module compiles with the host's pinned NDK. packages/core/android/build.gradle already reads compileSdkVersion, minSdkVersion, and targetSdkVersion from the host's rootProject.ext through safeExtGet, so I expected it to read ndkVersion the same way when the host sets one. react-native-screens, react-native-gesture-handler, react-native-svg, @stripe/stripe-react-native, react-native-reanimated, and Expo modules all do.

Actual Result

The build script never reads ndkVersion. With the New Architecture enabled the module has native code (externalNativeBuild { cmake { … } } and prefab true for ReactAndroid::reactnative), so AGP resolves an NDK for it and, since none is set, falls back to its own default and installs it during configuration. For AGP 8.12 that default is 27.0.12077973:

Checking the license for package NDK (Side by side) 27.0.12077973 in /usr/local/lib/android/sdk/licenses
Preparing "Install NDK (Side by side) 27.0.12077973 v.27.0.12077973".
Installing NDK (Side by side) 27.0.12077973 in /usr/local/lib/android/sdk/ndk/27.0.12077973

Effects: roughly a gigabyte downloaded per clean CI run on top of the pinned NDK, a configuration failure on offline or read-only SDK installs, and libsentry-tm-perf-logger.so built with a different NDK than the rest of the app.

Confirmed by adding a Gradle init script that prints each Android project's resolved ndkVersion after projectsEvaluated: with a stock root build.gradle, :sentry_react-native is the only project reporting null while every other one reports 27.1.12297006.

Proposed fix, keeping AGP's default when the host sets nothing:

android {
    compileSdkVersion safeExtGet('compileSdkVersion', 31)

    def hostNdkVersion = safeExtGet('ndkVersion', null)
    if (hostNdkVersion != null) {
        ndkVersion hostNdkVersion
    }
    //
}

Workaround we ship in the host root build.gradle meanwhile:

subprojects { subproject ->
  subproject.plugins.withId("com.android.library") {
    subproject.android.ndkVersion = rootProject.ext.ndkVersion
  }
}

Happy to open a PR with the one-line fix if that is easier.

Activity

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