You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "gnodet (via GitHub)" <gi...@apache.org> on 2026/06/18 05:18:55 UTC
[I] TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation [maven]
gnodet opened a new issue, #12302:
URL: https://github.com/apache/maven/issues/12302
## Description
Maven 4's default `TransitiveDependencyManager` (enabled when `maven3Personality=false`) changes dependency mediation behavior compared to Maven 3's `ClassicDependencyManager`. This causes two categories of regressions:
### 1. Scope derivation excludes transitive compile deps through provided parents
When a project declares a dependency with `provided` scope, `TransitiveDependencyManager` derives the effective scope of its transitive compile-scoped dependencies **during** collection (e.g., `provided × compile = provided`). The `ScopeDependencySelector.legacy(null, ["test", "provided"])` then filters them out at depth ≥ 1.
In Maven 3, scope derivation only happened **after** collection in the `DependencyGraphTransformer`, so the selector saw the declared scope `compile` and left the nodes in.
**Affected projects:** `hadoop-api-shim`, `flink-connector-hive`
Example dependency chain:
```
hadoop-api-shim
└── hadoop-common (scope: provided)
├── hadoop-annotations (scope: compile → derived: provided → EXCLUDED)
└── jsr305 (scope: compile → derived: provided → EXCLUDED)
```
### 2. Managed version application to transitive dependencies
`TransitiveDependencyManager` applies `<dependencyManagement>` versions at ALL depths during collection, not just to direct dependencies. This can **downgrade** transitive dependency versions, triggering `RequireUpperBoundDeps` and `BannedDependencies` enforcer rule violations that pass with Maven 3.
**Affected projects:** `guacamole-client`, `logging-log4j-samples`, `netbeans-html4j`
Example (guacamole-client):
```
Require upper bound dependencies error for com.google.code.findbugs:jsr305:3.0.1
+-guacamole-auth-header:1.6.1
+-guice:5.1.0
+-guava:32.1.3-jre (managed) <-- guava:30.1-jre
+-jsr305:3.0.1 (managed) <-- jsr305:3.0.2
```
Note the `(managed)` annotations — Maven 4 is applying the parent's `dependencyManagement` to transitive deps, downgrading jsr305 from 3.0.2 to 3.0.1.
## Root cause
`TransitiveDependencyManager.manageDependency()` applies managed versions/scopes at depth ≥ 2 during collection. Maven 3's `ClassicDependencyManager` did not do this — version management and scope derivation were handled post-collection in the graph transformer.
## Workaround
`-Dmaven.maven3Personality=true` reverts to `ClassicDependencyManager` behavior.
## Suggested fix
`ScopeDependencySelector.legacy` should use declared scopes from the POM, not derived scopes. The transitive version management should match Maven 3's behavior where managed versions are applied post-collection.
## Reproducers
```bash
# Scope derivation issue
git clone https://github.com/apache/hadoop-api-shim.git && cd hadoop-api-shim
mvn -B -e clean package -DskipTests
# Enforcer mediation issue
git clone https://github.com/apache/guacamole-client.git && cd guacamole-client
mvn -B -e clean package -DskipTests
```
## Context
Found during [Maven 4 compatibility testing](https://github.com/gnodet/maven4-testing/issues/13307) of Apache projects. Detailed root cause analysis in [hadoop-api-shim issue](https://github.com/gnodet/maven4-testing/issues/20241#issuecomment-4735787197).
_Claude Code on behalf of Guillaume Nodet_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation [maven]
Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet commented on issue #12302:
URL: https://github.com/apache/maven/issues/12302#issuecomment-4742750708
## Update: Category 1 (scope derivation) was a false positive
After comparing `toolbox:tree -DverboseTree` output between Maven 3 and Maven 4 for `flink-connector-hive`, the remaining Category 1 project also turns out to be caused by invalid Hadoop POMs, not by scope derivation changes.
**`flink-connector-hive`** depends on `hadoop-mapreduce-client-core:3.1.0` (provided) and `hadoop-yarn-registry:3.1.0` (compile). Both transitively depend on `hadoop-project:3.1.0`, which — like `hadoop-project:3.2.0` — contains invalid XML (`<Xlint:-unchecked/>`).
**Maven 3 verbose tree** shows all Hadoop transitives resolved:
```
+- hadoop-yarn-registry:3.1.0 [compile]
| +- hadoop-auth:3.1.0 [compile]
| +- hadoop-annotations:3.1.0 [compile]
| +- hadoop-yarn-api:3.1.0 [compile]
| +- hadoop-common:3.1.0 [compile]
+- hadoop-mapreduce-client-core:3.1.0 [provided]
| +- hadoop-yarn-client:3.1.0 [provided]
| +- hadoop-annotations:3.1.0 [compile]
```
**Maven 4 verbose tree** shows both Hadoop subtrees stripped:
```
WARNING: The POM for hadoop-mapreduce-client-core:3.1.0 is invalid,
transitive dependencies (if any) will not be available
WARNING: The POM for hadoop-yarn-registry:3.1.0 is invalid,
transitive dependencies (if any) will not be available
+- hadoop-yarn-registry:3.1.0 [compile] ← no children
+- hadoop-mapreduce-client-core:3.1.0 [provided] ← no children
```
Both `hadoop-api-shim` (hadoop-project:3.2.0) and `flink-connector-hive` (hadoop-project:3.1.0) fail for the same reason: Maven 4 correctly rejects invalid XML in the parent POM while Maven 3 silently accepts it.
**This issue now only covers Category 2** (managed version application to transitive dependencies). The issue body has been updated accordingly.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation [maven]
Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet commented on issue #12302:
URL: https://github.com/apache/maven/issues/12302#issuecomment-4751509112
Closing this issue — after investigation and discussion with Tamás Cservenák, the behavior described in case 2 (parent-inherited `<dependencyManagement>` affecting transitive dependency versions) is correct and by design.
`TransitiveDependencyManager` applies depMgmt "down the tree" within the same branch where it was discovered. When a POM inherits depMgmt from its parent, that management correctly applies to child nodes in its subtree. The resolver collects managed dependencies with `putIfAbsent` semantics (closer-to-root wins), so this does not leak sideways to other branches.
The fix for consumers who need a different version is to explicitly declare the dependency in their own `<dependencyManagement>` — root-level depMgmt is collected at depth 0 and takes precedence.
_Claude Code on behalf of Guillaume Nodet_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation [maven]
Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet commented on issue #12302:
URL: https://github.com/apache/maven/issues/12302#issuecomment-4738643062
## Analysis: Two distinct root causes in the reported regressions
After tracing through the code on the current `4.0.x` branch, I can confirm these are two separate bugs that both surface because `TransitiveDependencyManager` is now the default.
---
### Category 1 — Scope derivation / provided-scope exclusion
**Affected projects:** `hadoop-api-shim`, `flink-connector-hive`
**Pattern:** A `provided`-scope direct dep's transitive `compile` deps are missing from the compile classpath.
**Confirmed moving parts:**
1. **`ScopeDependencySelector.legacy()` explicitly excludes `provided` and `test` at depth >= 2 during collection** (`MavenSessionBuilderSupplier.java:102-105`). Any transitive dependency whose scope resolves to `provided` before the selector evaluates it gets dropped from the collected graph.
2. **`DependencyScope.PROVIDED.isTransitive() = false`** (`DependencyScope.java:77`). Maven 4's scope manager registers `provided` as non-transitive. In `Maven4ScopeManagerConfiguration`, `provided` falls into `nonTransitiveDependencyScopes`, which in `RS_MAIN_COMPILE` (ELIMINATE mode) means *its own transitive deps are not expanded onto the classpath*. A compile dep of a `provided` dep ends up as the `provided` dep's transitive dep — eligible for elimination.
3. **`ManagedScopeDeriver` narrows scope in `ConflictResolver`:** parent=`provided` × child=`compile` → derived=`provided` (narrowest wins, `ManagedScopeDeriver.java:74-81`). After the graph transformer runs, that compile transitive dep is now `provided`-scoped in the resolved graph, and its transitive closure is eliminated via (2).
**The TransitiveDependencyManager angle:** `TransitiveDependencyManager.isInheritedDerived()` returns `depth == 0` (only root-level depMgmt contributes managed scope), while `ClassicDependencyManager` effectively does the same due to its depth=1 hop. The scope narrowing therefore affects both managers equally at the collection phase. The regression likely comes from a *combination* of the new `ScopeDependencySelector.legacy()` (excluding provided from transitive collection) and the non-transitive scope semantics introduced with Maven 4's resolver integration, which were previously not applied in Maven 3 personality builds.
**Fix direction:** One of:
- Treat `provided`-scope deps' compile children as `compile` rather than narrowing them during graph transformation (adjust `ManagedScopeDeriver` scope table).
- Do not include `provided` in the `ScopeDependencySelector`'s excluded list for transitive dep collection (at least in Maven 3 personality mode).
- Revisit whether `DependencyScope.PROVIDED.isTransitive() = false` is semantically correct for backward compatibility — Maven 3 treated transitive compile deps of provided deps as accessible at compile time.
---
### Category 2 — Version downgrade via transitive dependencyManagement
**Affected projects:** `guacamole-client`, `logging-log4j-samples`, `netbeans-html4j`
**Pattern:** Enforcer rules (`RequireUpperBoundDeps`, `BannedDependencies`) fail because a version that should be stable is silently downgraded by a managed version in a transitive POM.
**Root cause — confirmed from code:**
| | `ClassicDependencyManager` | `TransitiveDependencyManager` |
|---|---|---|
| `deriveUntil` | `2` (+ depth=1 hop skips collection entirely) | `Integer.MAX_VALUE` |
| Version management sources | **Root depMgmt only** | **Every POM in the graph** |
`ClassicDependencyManager` (`ClassicDependencyManager.java:87,138`): the explicit depth=1 hop calls `newInstance` directly without processing `context.getManagedDependencies()`, and `deriveUntil=2` means depth >= 2 returns `this` unchanged. Only the root project's `<dependencyManagement>` contributes managed versions.
`TransitiveDependencyManager` (`TransitiveDependencyManager.java:94`): `deriveUntil = Integer.MAX_VALUE` means versions are collected from **every POM encountered** (`AbstractDependencyManager.deriveChildManager:329-334`). When an intermediate BOM/POM at depth N has a `<dependencyManagement>` entry with a lower version of artifact X, that version gets recorded. If X was not managed closer to the root, this lower version is applied — a version downgrade invisible to the user.
The "nearer wins" rule (`getManagedVersion` walks the `path` from root outward, returning the first match) does protect explicitly root-managed versions. But any coordinate that was only implicitly resolved (not in the root's depMgmt) can now be silently overridden by a deep transitive POM's depMgmt.
**Fix direction:** Apply `TransitiveDependencyManager`'s full-depth collection only for Maven 4 POMs (or only when the root explicitly opts in). For Maven 3-personality builds, revert to `ClassicDependencyManager` depth semantics. Alternatively, collect from all depths but only apply the collected version if no version has already been established by a higher-priority (nearer-to-root) source.
---
### Separate fixes are needed
These are independent bugs with different fix surfaces:
- **Category 1** → scope narrowing + `ScopeDependencySelector` + `provided` non-transitive semantics.
- **Category 2** → `deriveUntil` depth in `TransitiveDependencyManager`.
Fixing Category 2 alone (e.g., restoring `ClassicDependencyManager` as the default for Maven 3 personality) would not fix Category 1, which is about how provided-scope deps' children are treated during collection and classpath resolution in Maven 4's new scope model.
**Relevant source locations (`tmp-resolver` subtree on branch `4.0.x`):**
- `AbstractDependencyManager.java` — `deriveChildManager`, `manageDependency`, `getManagedVersion`
- `TransitiveDependencyManager.java:94` — `deriveUntil = MAX_VALUE, applyFrom = 2`
- `ClassicDependencyManager.java:87,138` — `deriveUntil = 2`, depth=1 hop
- `ScopeDependencySelector.java` (impl) — `legacy()` factory excluding `provided`+`test`
- `ManagedScopeDeriver.java:74-81` — narrowest-wins scope derivation
- `MavenSessionBuilderSupplier.java:89-106` — `TransitiveDependencyManager` wired as default
- `DependencyScope.java:77` — `PROVIDED("provided", false)` (non-transitive flag)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation [maven]
Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet closed issue #12302: TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation
URL: https://github.com/apache/maven/issues/12302
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] TransitiveDependencyManager changes dependency mediation, breaking enforcer rules and scope derivation [maven]
Posted by "gnodet (via GitHub)" <gi...@apache.org>.
gnodet commented on issue #12302:
URL: https://github.com/apache/maven/issues/12302#issuecomment-4740144540
## Update: hadoop-api-shim failure is caused by invalid POM on Maven Central
The `hadoop-api-shim` build failure is **not** caused by `TransitiveDependencyManager` — it is caused by an invalid POM published on Maven Central.
[`hadoop-project-3.2.0.pom`](https://repo.maven.apache.org/maven2/org/apache/hadoop/hadoop-project/3.2.0/hadoop-project-3.2.0.pom) contains invalid XML at line 1874: `<Xlint:-unchecked/>` — the `-` after the colon is not a valid XML name start character.
Maven 4 correctly rejects this:
```
[WARNING] The POM for org.apache.hadoop:hadoop-common:jar:3.2.0 is invalid,
transitive dependencies (if any) will not be available: 1 problem was
- [FATAL] Non-parseable POM org.apache.hadoop:hadoop-project:3.2.0:
Unable to read model: Unexpected character '-' (code 45)
(expected a name start character) at [row,col {unknown-source}]: [1874,12]
```
Because the parent POM is unparseable, `hadoop-common`'s transitive dependencies are unavailable, causing compilation failures.
**The scope derivation category (hadoop-api-shim, flink-connector-hive) should be retested with valid POMs** to determine if there is a genuine TransitiveDependencyManager regression independent of the invalid POM issue.
The enforcer rule category (guacamole-client, logging-log4j-samples, netbeans-html4j) may still be a genuine TransitiveDependencyManager issue — needs further investigation.
_Claude Code on behalf of Guillaume Nodet_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@maven.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org