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

Reply via email to