ReactRootProjectPlugin throws MissingPropertyException when the Android project contains nested Gradle subprojects (e.g., :lib:base included via include(":lib:base"), which implicitly creates a parent container project :lib).
The root cause is a Gradle property resolution inconsistency between hasProperty() and setProperty() for dotted property names across parent-child project hierarchies.
Error
- What went wrong:
An exception occurred applying plugin request id: 'com.facebook.react.rootproject'
Failed to apply plugin 'com.facebook.react.rootproject'.
Could not set unknown property 'react.newArchEnabled' for project ':lib:base' of type org.gradle.api.Project.
Caused by: groovy.lang.MissingPropertyException: Could not set unknown property 'react.newArchEnabled' for project ':lib:base' of type org.gradle.api.Project.
at org.gradle.internal.metaobject.AbstractDynamicObject.setMissingProperty(AbstractDynamicObject.java:123)
at org.gradle.internal.metaobject.AbstractDynamicObject.setProperty(AbstractDynamicObject.java:76)
at org.gradle.api.internal.project.DefaultDynamicLookupRoutine.setProperty(DefaultDynamicLookupRoutine.java:41)
at org.gradle.api.internal.project.DefaultProject.setProperty(DefaultProject.java:1198)
at com.facebook.react.ReactRootProjectPlugin$apply$1.execute(ReactRootProjectPlugin.kt:35)
Root Cause
In ReactRootProjectPlugin.kt (lines 34-41), the plugin iterates over all subprojects and sets new architecture properties:
project.subprojects { subproject ->
if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) { // "react.newArchEnabled"
subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") // ← crashes here
}
if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) { // "newArchEnabled"
subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true")
}
subproject.extraProperties.set(PropertyUtils.NEW_ARCH_ENABLED, "true")
subproject.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
}
The bug manifests through this sequence:
1. Gradle processes subprojects in order. When it processes the parent container project :lib, hasProperty("react.newArchEnabled") returns false (property doesn't exist yet), so setProperty is skipped. Then extraProperties.set("react.newArchEnabled", "true") (line 41) sets the property on :lib.
2. When Gradle processes the child project :lib:base, hasProperty("react.newArchEnabled") returns true — because Gradle's hasProperty() searches up the project hierarchy and finds the ext property set on parent :lib.
3. The code enters the if block and calls subproject.setProperty("react.newArchEnabled", "true"). However, setProperty() with a dotted name triggers Gradle's dynamic property resolution: it tries to find a react extension/object on :lib:base and set newArchEnabled on it. Since :lib:base has no react extension, it throws MissingPropertyException.
Key Gradle Behavior
Method
hasProperty("react.newArchEnabled")
setProperty("react.newArchEnabled", "true")
extraProperties.set("react.newArchEnabled", "true")
This inconsistency only manifests when a subproject has a parent project in the Gradle project tree — i.e., when using include(":group:module") syntax.
Reproduction
Minimal settings.gradle.kts
pluginManagement {
includeBuild("${rootProject.projectDir.parentFile.absolutePath}/node_modules/@react-native/gradle-plugin")
}
plugins {
id("com.facebook.react.settings")
}
extensions.configure<com.facebook.react.ReactSettingsExtension> {
autolinkLibrariesFromCommand()
}
rootProject.name = "ReproApp"
include(":app")
include(":lib:base") // ← This creates :lib container + :lib:base child
gradle.properties
newArchEnabled=true
Steps
1. Create a React Native 0.84.x project
2. Add a nested module: include(":lib:base") in settings.gradle.kts
3. Add newArchEnabled=true to gradle.properties
4. Run ./gradlew clean
Expected
Build succeeds. ReactRootProjectPlugin should handle nested subprojects gracefully.
Actual
Could not set unknown property 'react.newArchEnabled' for project ':lib:base'
Why Standard RN Projects Don't Hit This
The standard RN project template uses only top-level subprojects (:app, :react-native-xxx). Top-level projects have no parent (other than :root), and :root never gets react.newArchEnabled set on it by the plugin. So hasProperty always returns false for them.
Enterprise projects that organize native modules into groups (e.g., include(":lib:base"), include(":lib:network"), include(":lib:sdk")) will have implicit container projects (:lib) that trigger this bug.
Suggested Fix
Option A (recommended): Replace hasProperty + setProperty with direct extraProperties operations. The extraProperties.set calls on lines 40-41 already achieve the same goal with higher priority:
// Remove these blocks entirely — extraProperties.set below already handles everything:
// if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) {
// subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
// }
// if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) {
// subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true")
// }
// These two lines are sufficient:
subproject.extraProperties.set(PropertyUtils.NEW_ARCH_ENABLED, "true")
subproject.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
Option B: Use extraProperties.has() instead of hasProperty() to avoid parent project inheritance:
if (subproject.extensions.extraProperties.has(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) {
subproject.extensions.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
}
Workaround
Patch @react-native/gradle-plugin via patch-package:
if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) {
- subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
+ try {
+ subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true")
+ } catch (e: groovy.lang.MissingPropertyException) {}
}
if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) {
- subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true")
+ try {
+ subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true")
+ } catch (e: groovy.lang.MissingPropertyException) {}
}
Environment
- React Native: 0.84.1
- @react-native/gradle-plugin: 0.84.1
- Gradle: 9.0.0
- AGP: 8.12.0
- OS: macOS
ReactRootProjectPluginthrowsMissingPropertyExceptionwhen the Android project contains nested Gradle subprojects (e.g.,:lib:baseincluded viainclude(":lib:base"), which implicitly creates a parent container project:lib).The root cause is a Gradle property resolution inconsistency between
hasProperty()andsetProperty()for dotted property names across parent-child project hierarchies.Error
An exception occurred applying plugin request id: 'com.facebook.react.rootproject'
Failed to apply plugin 'com.facebook.react.rootproject'.
Could not set unknown property 'react.newArchEnabled' for project ':lib:base' of type org.gradle.api.Project.
Caused by: groovy.lang.MissingPropertyException: Could not set unknown property 'react.newArchEnabled' for project ':lib:base' of type org.gradle.api.Project.
at org.gradle.internal.metaobject.AbstractDynamicObject.setMissingProperty(AbstractDynamicObject.java:123)
at org.gradle.internal.metaobject.AbstractDynamicObject.setProperty(AbstractDynamicObject.java:76)
at org.gradle.api.internal.project.DefaultDynamicLookupRoutine.setProperty(DefaultDynamicLookupRoutine.java:41)
at org.gradle.api.internal.project.DefaultProject.setProperty(DefaultProject.java:1198)
at com.facebook.react.ReactRootProjectPlugin$apply$1.execute(ReactRootProjectPlugin.kt:35)
Root Cause
In
ReactRootProjectPlugin.kt(lines 34-41), the plugin iterates over all subprojects and sets new architecture properties:project.subprojects { subproject -> if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) { // "react.newArchEnabled" subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") // ← crashes here } if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) { // "newArchEnabled" subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true") } subproject.extraProperties.set(PropertyUtils.NEW_ARCH_ENABLED, "true") subproject.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") } The bug manifests through this sequence: 1. Gradle processes subprojects in order. When it processes the parent container project :lib, hasProperty("react.newArchEnabled") returns false (property doesn't exist yet), so setProperty is skipped. Then extraProperties.set("react.newArchEnabled", "true") (line 41) sets the property on :lib. 2. When Gradle processes the child project :lib:base, hasProperty("react.newArchEnabled") returns true — because Gradle's hasProperty() searches up the project hierarchy and finds the ext property set on parent :lib. 3. The code enters the if block and calls subproject.setProperty("react.newArchEnabled", "true"). However, setProperty() with a dotted name triggers Gradle's dynamic property resolution: it tries to find a react extension/object on :lib:base and set newArchEnabled on it. Since :lib:base has no react extension, it throws MissingPropertyException. Key Gradle Behavior Method hasProperty("react.newArchEnabled") setProperty("react.newArchEnabled", "true") extraProperties.set("react.newArchEnabled", "true") This inconsistency only manifests when a subproject has a parent project in the Gradle project tree — i.e., when using include(":group:module") syntax. Reproduction Minimal settings.gradle.kts pluginManagement { includeBuild("${rootProject.projectDir.parentFile.absolutePath}/node_modules/@react-native/gradle-plugin") } plugins { id("com.facebook.react.settings") } extensions.configure<com.facebook.react.ReactSettingsExtension> { autolinkLibrariesFromCommand() } rootProject.name = "ReproApp" include(":app") include(":lib:base") // ← This creates :lib container + :lib:base child gradle.properties newArchEnabled=true Steps 1. Create a React Native 0.84.x project 2. Add a nested module: include(":lib:base") in settings.gradle.kts 3. Add newArchEnabled=true to gradle.properties 4. Run ./gradlew clean Expected Build succeeds. ReactRootProjectPlugin should handle nested subprojects gracefully. Actual Could not set unknown property 'react.newArchEnabled' for project ':lib:base' Why Standard RN Projects Don't Hit This The standard RN project template uses only top-level subprojects (:app, :react-native-xxx). Top-level projects have no parent (other than :root), and :root never gets react.newArchEnabled set on it by the plugin. So hasProperty always returns false for them. Enterprise projects that organize native modules into groups (e.g., include(":lib:base"), include(":lib:network"), include(":lib:sdk")) will have implicit container projects (:lib) that trigger this bug. Suggested Fix Option A (recommended): Replace hasProperty + setProperty with direct extraProperties operations. The extraProperties.set calls on lines 40-41 already achieve the same goal with higher priority: // Remove these blocks entirely — extraProperties.set below already handles everything: // if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) { // subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") // } // if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) { // subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true") // } // These two lines are sufficient: subproject.extraProperties.set(PropertyUtils.NEW_ARCH_ENABLED, "true") subproject.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") Option B: Use extraProperties.has() instead of hasProperty() to avoid parent project inheritance: if (subproject.extensions.extraProperties.has(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) { subproject.extensions.extraProperties.set(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") } Workaround Patch @react-native/gradle-plugin via patch-package: if (subproject.hasProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED)) { - subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") + try { + subproject.setProperty(PropertyUtils.SCOPED_NEW_ARCH_ENABLED, "true") + } catch (e: groovy.lang.MissingPropertyException) {} } if (subproject.hasProperty(PropertyUtils.NEW_ARCH_ENABLED)) { - subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true") + try { + subproject.setProperty(PropertyUtils.NEW_ARCH_ENABLED, "true") + } catch (e: groovy.lang.MissingPropertyException) {} } Environment - React Native: 0.84.1 - @react-native/gradle-plugin: 0.84.1 - Gradle: 9.0.0 - AGP: 8.12.0 - OS: macOS