Skip to content

Mathbl/expo-brownfield-setversion-bug

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

expo-brownfield setVersion duplicate <version> bug — minimal reproducer

Demonstrates the expo-brownfield Android publish bug filed at expo/expo#45749.

TL;DR

expo-brownfield's POM rewriter (introduced in PR #43693, present in 55.0.22 / 55.0.23) emits two <version> elements inside the react-android dependency of any subproject that declares implementation "com.facebook.react:react-android:$reactNativeVersion". Maven rejects the duplicate → publishBrownfieldReleasePublicationToMavenLocal fails.

react-native-keyboard-controller@1.20.7 is one such subproject (used here to trigger the bug).

How this repro was created

bunx create-expo-app@latest app --template default@sdk-55 --no-install
cd app
bun install
bunx expo install expo-brownfield react-native-keyboard-controller
bunx expo prebuild --clean --platform android
bunx expo-brownfield build:android --repo MavenLocal -r --verbose

No source code changes — only a default create-expo-app SDK 55 project with two packages installed and the expo-brownfield plugin auto-registered via expo install.

Resulting POM at app/node_modules/react-native-keyboard-controller/android/build/publications/brownfieldRelease/pom-default.xml

<dependency>
  <groupId>com.facebook.react</groupId>
  <artifactId>react-android</artifactId>
  <version>+</version>
  <scope>runtime</scope>
  <version>0.83.6</version>   <!-- appended by setVersion — bug -->
</dependency>

Error

> Task :react-native-keyboard-controller:publishBrownfieldReleasePublicationToMavenLocal FAILED

* What went wrong:
Execution failed for task ':react-native-keyboard-controller:publishBrownfieldReleasePublicationToMavenLocal'.
> Failed to publish publication 'brownfieldRelease' to repository 'mavenLocal'
   > Invalid publication 'brownfieldRelease': POM file is invalid. Check any modifications you have made to the POM file.

Cause

packages/expo-brownfield/gradle-plugins/publish/src/main/kotlin/expo/modules/plugin/extensions.kt:107:

internal fun Node.setVersion(version: String) {
  val versionNode = this.children().firstOrNull { it is Node && it.name() == "version" } as? Node
  if (versionNode != null) {
    versionNode.setValue(version)
  } else {
    this.appendNode("version", version)
  }
}

Node.name() returns a QName-like object that doesn't == a String, so firstOrNull always returns null and appendNode runs every time — even when a <version> element is already present in the dependency node.

Sibling helpers (groupId(), artifactId()) in the same file use the correct get(...) / NodeList pattern.

Proposed fix

internal fun Node.setVersion(version: String) {
  val node = when (val v = this.get("version")) {
    is Node -> v
    is NodeList -> v.firstOrNull() as? Node
    else -> null
  }
  if (node != null) node.setValue(version) else this.appendNode("version", version)
}

Environment

  • expo-brownfield 55.0.23 (also reproduces on 55.0.22)
  • Expo SDK 55, react-native 0.83.6
  • Gradle 9.0.1
  • AGP from SDK 55 default
  • macOS 26.4, Node 22.22.2

About

Minimal reproducer for expo-brownfield setVersion duplicate <version> bug (expo/expo#45749)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors