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]

Reply via email to