What version of OpenRewrite are you using?
Latest main (reproduced at 560b40c).
What is the smallest, simplest way to reproduce the problem?
In a multi-module build, a child module declares a dependency without a <version> and the parent POM manages it. ChangeDependencyGroupIdAndArtifactId renames the dependency in the child and the <dependencyManagement> entry in the parent — deliberately not writing an explicit version into the child (see providedDependencyManagedByLocalParentDoesNotGetExplicitVersion, parentAndBomManagedToJustParentManaged).
That output is correct on disk, but the child document's MavenResolutionResult still holds the parent's parse-time model, in which the old coordinates are managed and the new ones are not. Any recipe that runs afterwards in the same run and calls maybeUpdateModel() on the child then re-resolves against that stale parent and fails:
rewriteRun(
spec -> spec.recipes(
new ChangeDependencyGroupIdAndArtifactId("com.squareup.okhttp3", "mockwebserver", null, "mockwebserver3", "5.x", null),
new RemoveDependency("org.awaitility", "awaitility", null)), // any recipe that updates the model
// parent POM: <dependencyManagement> for com.squareup.okhttp3:mockwebserver
// child POM: <dependency> com.squareup.okhttp3:mockwebserver with no <version>
);
What did you expect to see?
No marker: after the run, the parent manages mockwebserver3 and the child resolves.
What did you see instead?
<!--~~(No version provided for direct dependency com.squareup.okhttp3:mockwebserver3:compile)~~>--><dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver3</artifactId>
</dependency>
Two consequences:
- Error markers on every child module, on POMs that are actually fine. Observed in a Moderne SaaS run of "Spring Boot 4.0 best practices": 56 markers across
spring-cloud/spring-cloud-sleuth (30) and spring-projects-experimental/spring-cloud-sleuth-otel (26), all from UpgradeOkHttpMockWebServer -> ChangeDependency. The full spring-cloud-sleuth POM chain (root → tests → tests/brave → module) reproduces it exactly.
- Worse, later recipes make decisions from the stale model.
AddDependency for the new coordinates sees a model that still lists the old ones and can add a second, duplicate <dependency> next to the renamed one — which is what finos/legend-shared shows for jakarta.ws.rs:jakarta.ws.rs-api.
The staleness is structural: each document has its own MavenResolutionResult, and UpdateMavenModel re-resolves a child through getProjectPoms(), which yields the parent's requested Pom as captured at parse time. Edits to the parent document do not propagate to a child document's getParent() within the same pass.
Are you interested in contributing a fix?
What version of OpenRewrite are you using?
Latest
main(reproduced at 560b40c).What is the smallest, simplest way to reproduce the problem?
In a multi-module build, a child module declares a dependency without a
<version>and the parent POM manages it.ChangeDependencyGroupIdAndArtifactIdrenames the dependency in the child and the<dependencyManagement>entry in the parent — deliberately not writing an explicit version into the child (seeprovidedDependencyManagedByLocalParentDoesNotGetExplicitVersion,parentAndBomManagedToJustParentManaged).That output is correct on disk, but the child document's
MavenResolutionResultstill holds the parent's parse-time model, in which the old coordinates are managed and the new ones are not. Any recipe that runs afterwards in the same run and callsmaybeUpdateModel()on the child then re-resolves against that stale parent and fails:What did you expect to see?
No marker: after the run, the parent manages
mockwebserver3and the child resolves.What did you see instead?
Two consequences:
spring-cloud/spring-cloud-sleuth(30) andspring-projects-experimental/spring-cloud-sleuth-otel(26), all fromUpgradeOkHttpMockWebServer -> ChangeDependency. The fullspring-cloud-sleuthPOM chain (root →tests→tests/brave→ module) reproduces it exactly.AddDependencyfor the new coordinates sees a model that still lists the old ones and can add a second, duplicate<dependency>next to the renamed one — which is whatfinos/legend-sharedshows forjakarta.ws.rs:jakarta.ws.rs-api.The staleness is structural: each document has its own
MavenResolutionResult, andUpdateMavenModelre-resolves a child throughgetProjectPoms(), which yields the parent's requestedPomas captured at parse time. Edits to the parent document do not propagate to a child document'sgetParent()within the same pass.Are you interested in contributing a fix?