Diagnosing and Resolving Maven Dependency Version Conflicts in Multi‑Module Projects
When Maven builds fail with convergence errors or runtime class issues, a hidden version conflict is likely. This guide walks through symptom identification, diagnostic steps, and targeted fixes for multi‑module projects.
18 Sept 2026, 13:36 UTC

Problem Statement
When a Maven build fails with a Dependency convergence error or a running application throws ClassNotFoundException, NoSuchMethodError, or LinkageError, the most common culprit is a version conflict on the classpath. In a multi‑module project this can stem from direct, transitive, or profile‑specific dependencies that pull in incompatible artifact versions.
Recognizable Symptoms & Diagnosis Table
| Symptom | Likely Cause | Diagnostic Command |
|---|---|---|
Build fails with enforcer:enforce convergence error | Direct + transitive version mismatch | mvn dependency:tree -Dverbose -Dincludes=groupId:artifactId |
Runtime NoSuchMethodError | Diamond dependency with incompatible versions | mvn dependency:analyze-duplicate |
| Different versions packaged in WAR vs EAR | Module‑specific transitive resolution | mvn help:effective-pom -pl <module> |
| Tests pass but integration tests fail | Test‑scope dependency leaking into compile | mvn dependency:tree -Dscope=test |
Ordered Verification Steps
- Run the enforcer plugin first (if configured) to surface convergence violations:
mvn validate enforce:enforceRequires
maven-enforcer-pluginin the parent POM and theenforcegoal bound to thevalidatephase. - Map the full dependency graph for the artifact in question:
mvn dependency:tree -Dverbose -Dincludes=org.example:my-libUse
-DoutputFile=tree.txtif the graph exceeds the 1,000‑line default. - Detect duplicate classes that could cause runtime clashes:
mvn dependency:analyze-duplicateInspect the
duplicate-classes.txtreport for classes found in multiple jars. - Inspect effective POMs per module to see if a module overrides a parent
dependencyManagemententry or activates a profile that pulls a different version:mvn help:effective-pom -pl <module> -DoutputFile=effective-pom.xml - Verify the exact artifacts downloaded (snapshot vs release, mirror metadata):
mvn dependency:resolve -Dclassifier=sourcesCheck the local repository path in the output to confirm the version.
Targeted Fixes
- Convergence error – Pin the version in
dependencyManagementof the root POM, or exclude the offending version from the transitive dependency:<dependencyManagement> <dependency> <groupId>org.example</groupId> <artifactId>my-lib</artifactId> <version>1.4.2</version> </dependency> </dependencyManagement> - Diamond conflict – Declare the desired version directly in the child module’s
dependenciessection; Maven’s nearest‑wins rule will then use that version over the transitive one. - Module divergence – Remove any module‑level overrides that conflict with the parent
dependencyManagementand rely on the central version. - Test‑scope leak – Ensure that test‑only dependencies are declared with
<scope>test</scope>and that no transitive dependency pulls them into compile. If necessary, add a<exclusion>to the transitive dependency that brings in the test artifact.
Concrete Example
Suppose module web pulls in commons-lang3:3.9 via spring-core, while module core explicitly depends on commons-lang3:3.12.0. The build reports a convergence error.
mvn validate enforce:enforce
[ERROR] Dependency convergence error:
commons-lang3:commons-lang3:jar:3.9
commons-lang3:commons-lang3:jar:3.12.0
Fix: add a dependencyManagement entry in the parent POM and declare commons-lang3 as 3.12.0 there. Then both modules will resolve to the same version, and the enforcer will pass.
Escalation Criteria
- Conflict involves a legacy jar without an
Automatic-Module-Name, requiring shading or relocation. - Pinning a version breaks a downstream consumer; a BOM import is needed instead of direct dependency.
- Resolution depends on a corrupted mirror; run
mvn dependency:purge-local-repositoryand verify withmvn dependency:resolve. - Cross‑module circular dependency detected; refactor the modules to break the cycle.
- Security CVE mandates a version upgrade that is incompatible with the existing API; coordinate with the team for a migration plan.
Verification Checklist
- Run
mvn validate enforce:enforce– should report no convergence violations. - Execute
mvn dependency:analyze– should show no undeclared or unused dependencies. - Deploy the artifact to a staging repository and import it into a fresh consumer project; run
mvn dependency:treeto confirm the transitive version. - Run
mvn failsafe:integration-test -Pallto ensure all profiles succeed. - Inspect the packaged WAR with
jar tf target/web.war | grep commons-lang3– only the pinned version should appear.
Limitations & Practical Checks
- The
dependency:treegoal truncates after 1,000 lines; use-DoutputFilefor larger projects. - Exclusions are transitive – excluding a dependency from one parent does not remove it if another dependency pulls it in.
- Snapshot artifacts may resolve to a timestamped file; use
-Uto force a fresh download. - Profile‑activated dependencies can silently change resolution; always run diagnostics with
-Pall. - Offline mode (
-o) hides resolution failures; run diagnostics online first.
Conclusion
By following the ordered checks, mapping the dependency graph, and applying targeted fixes, most Maven version conflicts in multi‑module projects can be resolved quickly. When the problem persists beyond the escalation thresholds, consider refactoring module boundaries, adopting a Bill‑of‑Materials (BOM), or engaging the wider community for a long‑term solution.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.