Skip to content

ReactRootProjectPlugin: "Could not set unknown property 'react.newArchEnabled'" on nested Gradle subprojects #1012

Description

@SunshineSeed77

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions