Affected versions
- maven-shade-plugin master (a6c103f5).
- Building under Maven 4.0.0-SNAPSHOT (commit
0a61d8348b, 2026-06-27 — shortly before the 4.0.0-rc-6 cut).
- Does NOT reproduce under Maven 3.9.16 (see below) — this is Maven-4-specific.
Symptom (not a build failure)
The plugin compiles, packages, and passes all unit tests against 4.0.0-SNAPSHOT; only 2 of 84 integration tests fail, and both fail on the content of the generated dependency-reduced-pom.xml — not a build/compile error: dep-reduced-pom-exclusions and MSHADE-467_parallel-dependency-reduced-pom.
When a shaded dependency has a transitive dependency that occurs as a classifier-distinct duplicate (b:0.2 and b:0.2:alt) and that dependency carries an <exclusion>, the generated dependency-reduced POM keeps the <exclusion> on only ONE of the two variants; the classifier variant ends up with none.
Maven 3 vs Maven 4
- Maven 3.9.16: both ITs PASS — both
b variants carry the exclusion.
- Maven 4.0.0-SNAPSHOT: both fail —
b:0.2:alt has 0 exclusions (expected 1); MSHADE-467 exclusion count 3 vs 5.
Root cause
ShadeMojo.updateExcludesInDeps() discovers each direct dependency's transitive set via a single repositorySystem.collectDependencies(...) (~ShadeMojo.java:1302) and walks node.getChildren(). Under Maven 4 that collected graph is conflict-resolved with the second c omitted (omitted for duplicate) under b:0.2:alt, so shade never sees c as a child of the classifier variant and applies the exclusion to b:0.2 only. Shade's own dependency keying (getId() = groupId:artifactId:type:classifier) is classifier-aware and not at fault.
Suggested fix — two alternatives (either resolves it; both keep Maven 3 green)
- Collect with resolver verbose conflict resolution (
aether.conflictResolver.verbose=true) so the omitted-duplicate node is retained as a marker (shade only needs its groupId:artifactId); the existing walk then finds c under both b variants. or
- Collect each direct dependency independently (its own
CollectRequest) so the duplicate never arises, mapping subtrees back via the existing classifier-aware getId.
Regression coverage already exists: the two ITs above (red on Maven 4, green on Maven 3).
Affected versions
0a61d8348b, 2026-06-27 — shortly before the 4.0.0-rc-6 cut).Symptom (not a build failure)
The plugin compiles, packages, and passes all unit tests against 4.0.0-SNAPSHOT; only 2 of 84 integration tests fail, and both fail on the content of the generated
dependency-reduced-pom.xml— not a build/compile error:dep-reduced-pom-exclusionsandMSHADE-467_parallel-dependency-reduced-pom.When a shaded dependency has a transitive dependency that occurs as a classifier-distinct duplicate (
b:0.2andb:0.2:alt) and that dependency carries an<exclusion>, the generated dependency-reduced POM keeps the<exclusion>on only ONE of the two variants; the classifier variant ends up with none.Maven 3 vs Maven 4
bvariants carry the exclusion.b:0.2:althas 0 exclusions (expected 1);MSHADE-467exclusion count 3 vs 5.Root cause
ShadeMojo.updateExcludesInDeps()discovers each direct dependency's transitive set via a singlerepositorySystem.collectDependencies(...)(~ShadeMojo.java:1302) and walksnode.getChildren(). Under Maven 4 that collected graph is conflict-resolved with the secondcomitted (omitted for duplicate) underb:0.2:alt, so shade never seescas a child of the classifier variant and applies the exclusion tob:0.2only. Shade's own dependency keying (getId()=groupId:artifactId:type:classifier) is classifier-aware and not at fault.Suggested fix — two alternatives (either resolves it; both keep Maven 3 green)
aether.conflictResolver.verbose=true) so the omitted-duplicate node is retained as a marker (shade only needs itsgroupId:artifactId); the existing walk then findscunder bothbvariants. orCollectRequest) so the duplicate never arises, mapping subtrees back via the existing classifier-awaregetId.Regression coverage already exists: the two ITs above (red on Maven 4, green on Maven 3).