Howdy, just as a side note, as classpath was mentioned as well, Maven 4 does it differently too: https://gist.github.com/cstamas/289876994937fbda937c47494998bebe
Notice how the tree was transformed into a (classpath) list: "deepest" nodes are last on classpath list, as Maven 4 finally does "level order" (maven3 does pre-order). T On Wed, Oct 22, 2025 at 11:57 AM Tamás Cservenák <[email protected]> wrote: > > Howdy, > > Using your reproducer: [email protected]:vlsi/mvn-mediation.git at > dd5f3a484634c04fb36da22e931cd51be2a68e6c > using maven master (but revent 4.0.0 would do as well): > > [cstamas@angeleyes mvn-mediation (main)]$ mvn -v > Apache Maven 4.1.0-SNAPSHOT (448a6d756351d2b567e498d4087b9637ea69cb0e) > Maven home: /home/cstamas/.sdkman/candidates/maven/latest-master > Java version: 21.0.8, vendor: Eclipse Adoptium, runtime: > /home/cstamas/.sdkman/candidates/java/21.0.8-tem > Default locale: en_US, platform encoding: UTF-8 > OS name: "linux", version: "6.16.12-200.fc42.x86_64", arch: "amd64", > family: "unix" > [cstamas@angeleyes mvn-mediation (main)]$ > > My local results: > (lib-b-a; unchanged commit hash of your repo) > https://gist.github.com/cstamas/d30b7c682f50ad81c6996fc35d70e317 > (lib-a-b; as above but locally altered dep order in example application) > https://gist.github.com/cstamas/7ac9ead53539a3dce88cc154c15faa4b > > In this gist above, the first invocation (despite params present, they > are "defaults"), second invocation uses "highest" instead of maven > default "nearest" strategy. > > So as you see, in first invocation is as you say: > - guava 33.5 wins > - guice 3.0 wins > = breakage > > If I use "highest" strategy, it works, as in this reproducer no direct > deps are involved (maven will never override user instructions): > - guava 33.5 wins as before > - but guice 5.0.1 wins (over 3.0) > > > So, in this case, as no direct deps override is expected, it works as > expected, no? > > Thanks > T > > On Wed, Oct 15, 2025 at 1:21 PM Vladimir Sitnikov > <[email protected]> wrote: > > > > Hi devs, > > > > Per previous guidance to move this discussion to the mailing list, I’m > > following up on Maven’s dependency > > mediation rules (“nearest first” / “declared first”) with a concrete > > reproducer and a proposal for next steps. > > > > Reproducer: https://github.com/vlsi/mvn-mediation > > > > # Background, problem statement > > > > In MNG-7852 [1] / issue#9070 [2], I outlined why “nearest/declared first” > > leads to hard-to-reason classpaths and frequent downgrades > > of transitives that users cannot practically control (depth/order are > > effectively random from an application author’s perspective). > > > > A real failure we hit: adding dev.sigstore:sigstore-java results in Maven > > selecting an older protobuf-java at runtime > > than the one used at compile time. > > Hervé Boutemy analyzed this case [3] > > > > Prior work such as MNG-5988 shows another facet: a test-scoped path can win > > by being nearer, > > effectively impacting the compile/runtime classpath which is > > counterintuitive and risky. > > The issue text and comments document how a nearer test path overrides a > > farther compile path, and why that surprises users. > > > > # What the reproducer demonstrates > > > > With two “third-party” deps that each bring different versions of the same > > library, the outcome flips based on tree shape > > or declaration order, producing an incompatible classpath without any > > explicit signal to the user. > > The repo has small modules that make this visible with dependency:tree and > > a tiny runtime check. > > > > # Why I believe this is worth revisiting > > > > “Nearest/declared first” is predictable to *Maven*, but it’s not > > *controllable* to end-users unless they redundantly re-declare > > virtually all transitives (including runtime-only) via > > dependencyManagement, which is brittle and tends to go stale. > > It is exactly the failure mode highlighted in MNG-7852 and in Hervé’s > > analysis. > > > > MNG-5988 illustrates that scope semantics (e.g., test vs compile) can be > > undermined by the current tie-breakers, making production classpaths depend > > on test paths. > > > > # A concrete direction to discuss > > > > * Consider all occurrences, then mediate > > Expand the full graph, then choose a version after seeing all constraints > > rather than “first mention wins.” > > This mirrors how many ecosystems approach version resolution. > > > > * Migration path / safety rails > > Provide an experimental switch (resolver/system property) that computes > > both legacy and proposed results; if they differ, emit a warning showing > > the two choices and why. > > I think it would be better to make "highest wins" the default for Maven 4 > > poms, and it would be great to have a flag for Maven 3 as well > > Offer a fail-on-divergence mode for CI to surface risky downgrades early. > > Document how BOMs/depMgmt interact under the new strategy. > > > > # Specific questions for the team > > > > 1. Would an experimental “consider-all + prefer-highest” mediation behind a > > flag be acceptable for an initial PR (likely touching Maven Resolver first)? > > 2. If full “prefer-highest” is too big a jump, what could be the approach > > to address the issue? > > > > I’m happy to iterate on the approach and prototype if this direction sounds > > reasonable. > > > > [1] https://issues.apache.org/jira/browse/MNG-7852 > > [2] https://github.com/apache/maven/issues/9070 > > [3] > > https://github.com/hboutemy/sigstore-maven-plugin/blob/bdf6fbcad0494011c7726456eb61425116a43339/analysis.md > > > > Regards, > > Vladimir --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
