Skip to content

Maven Dependency Version Conflict Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about Maven Dependency Version Conflict Fix. We cover key concepts, practical examples, and best practices.

Your Maven build fails with javax.xml.bind.JAXBException at runtime or ClassNotFoundException — two dependencies pull different versions of the same transitive library, causing runtime incompatibilities.

Step-by-Step Fix

1. View the dependency tree

# Wrong: guessing which version is being used
# Right: use the dependency tree to see conflicts

mvn dependency:tree -Dverbose

# Filter for a specific dependency
mvn dependency:tree -Dincludes=com.google.guava:guava

Expected output:

[INFO] com.mycompany:my-app:jar:1.0.0
[INFO] +- com.squareup.okhttp3:okhttp:jar:4.12.0:compile
[INFO] |  \- com.squareup.okio:okio:jar:3.6.0:compile
[INFO] \- com.squareup.retrofit2:retrofit:jar:2.9.0:compile
[INFO]    \- com.squareup.okhttp3:okhttp:jar:3.14.9:compile (version managed from 3.14.9 to 4.12.0)

2. Use dependency management to pin versions

<!-- Wrong: no dependency management, Maven uses nearest-wins strategy -->
<project>
  <dependencies>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.1-jre</version>
    </dependency>
    <!-- Another dependency pulls in guava 30.0 -->
  </dependencies>
</project>

<!-- Right: use dependencyManagement to pin versions -->
<project>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>32.1.3-jre</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <!-- Version inherited from dependencyManagement -->
    </dependency>
  </dependencies>
</project>

3. Exclude transitive dependencies

<!-- Wrong: conflicting transitive dependency from multiple sources -->
<project>
  <dependencies>
    <dependency>
      <groupId>com.squareup.retrofit2</groupId>
      <artifactId>retrofit</artifactId>
      <version>2.9.0</version>
      <!-- Pulls in okhttp 3.x, conflicting with okhttp 4.x below -->
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>4.12.0</version>
    </dependency>
  </dependencies>
</project>

<!-- Right: exclude the transitive dependency -->
<project>
  <dependencies>
    <dependency>
      <groupId>com.squareup.retrofit2</groupId>
      <artifactId>retrofit</artifactId>
      <version>2.9.0</version>
      <exclusions>
        <exclusion>
          <groupId>com.squareup.okhttp3</groupId>
          <artifactId>okhttp</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <version>4.12.0</version>
    </dependency>
  </dependencies>
</project>

4. Use a BOM for consistent versions

<!-- Import a Bill of Materials to manage versions consistently -->
<project>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.fasterxml.jackson</groupId>
        <artifactId>jackson-bom</artifactId>
        <version>2.16.1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>3.2.1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <!-- Versions managed by BOM -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>
</project>

5. Check for duplicate classes

# Check for duplicate/multiple versions of the same class on classpath
mvn dependency:tree -Dincludes=javax.xml.bind

# Or check specific packages
mvn help:effective-pom

6. Use enforcer plugin to detect conflicts

<project>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>3.4.1</version>
        <executions>
          <execution>
            <id>enforce-dependency-convergence</id>
            <goals><goal>enforce</goal></goals>
            <configuration>
              <rules>
                <dependencyConvergence/>
                <bannedDependencies>
                  <excludes>
                    <exclude>commons-logging:*</exclude>
                  </excludes>
                </bannedDependencies>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Prevention

  • Always run mvn dependency:tree to understand your full dependency graph.
  • Use dependencyManagement to pin critical dependency versions.
  • Use BOM files from framework providers (Spring Boot, Jackson, AWS SDK).
  • Use the Maven Enforcer plugin's dependencyConvergence rule.
  • Exclude unnecessary transitive dependencies explicitly.

Common Mistakes with dependency tree

  1. Mixing let bindings with <- bindings in do notation, producing type errors
  2. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  3. Non-exhaustive pattern matches that compile with warnings then crash at runtime

These mistakes appear frequently in real-world MAVEN code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

How does Maven resolve dependency version conflicts?

Maven uses the "nearest wins" strategy: the version closest to the project root in the dependency tree is selected. To control this, use dependencyManagement to explicitly pin versions. |||What is a BOM (Bill of Materials)? A BOM is a special POM that manages dependency versions for a set of libraries. Importing a BOM in dependencyManagement ensures all related dependencies use compatible versions. |||How do I see which version of a dependency is actually used? Run mvn dependency:tree -Dincludes=<groupId>:<artifactId>. Maven shows the resolved version after conflict resolution, marked with (version managed from X to Y).

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro