skip to content

A NoSuchMethodError appears at runtime that you suspect is a dependency version conflict. Walk me through how you'd diagnose and fix it.

level: seniorimportance: should knowfreq 65%

answer

  1. NoSuchMethodError = wrong version won mediation
  2. mvn dependency:tree -Dverbose -Dincludes=...
  3. 'omitted for conflict' lines
  4. fix: dependencyManagement > direct > exclude
  5. prevent: enforcer dependencyConvergence + BOM

basics

~10 s

Run mvn dependency:tree (with -Dverbose) to find which versions of the artifact are in the graph and which one mediation chose. Then force the correct version via dependencyManagement or a direct declaration, and re-verify.

solid answer

~40 s

A NoSuchMethodError/NoClassDefFoundError at runtime usually means the wrong version of an artifact won mediation — the chosen version lacks a method that compiled code expects. Diagnosis: run `mvn dependency:tree -Dverbose -Dincludes=group:artifact` to see every occurrence, their depths, and the `(omitted for conflict)` notes showing what Maven dropped. Confirm the resolved version is older/incompatible. Fix options, in order of preference: (1) pin the correct version in `<dependencyManagement>` so it applies graph-wide regardless of depth; (2) declare it directly (depth 1) if it's something you use; (3) exclude the bad path and let the good one win. Then re-run dependency:tree to confirm convergence and run tests. To prevent recurrence, add the maven-enforcer-plugin `dependencyConvergence` rule so divergence fails the build, and prefer BOM imports for version alignment.

code

bash · 5 lines
bash
# find all versions of the artifact and what was dropped
mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core:jackson-databind
# look for lines like:
#   (jackson-databind:2.13.0 - omitted for conflict with 2.9.0)
# then pin 2.13.0 in <dependencyManagement> and re-run + test

go deeper

for a junior

Know to run mvn dependency:tree when classpath errors appear.

for a middle

Use -Dverbose/-Dincludes to read omitted-for-conflict lines and pin the version.

for a senior

Choose the right fix (dependencyManagement vs direct vs exclude) and verify with tests.

for a principal

Institutionalize prevention: enforcer convergence in the parent POM, BOM-based version governance, CVE scanning of the transitive graph.

## Why this happens Code is **compiled** against version X of an artifact (which has method `foo()`), but at **runtime** mediation selected a nearer, older version Y that lacks `foo()`. The JVM throws `NoSuchMethodError` (method missing) or `NoClassDefFoundError` (class/relocation missing). This is the classic symptom of a transitive version conflict. ## Step 1 — see the graph ```bash mvn dependency:tree -Dverbose -Dincludes=com.example:libC ``` - `-Dverbose` shows the `(omitted for conflict with N)` lines — i.e. versions Maven discarded during mediation. - `-Dincludes=group:artifact` filters to just the suspect artifact. Identify: which version won, at what depth, and which versions were omitted. ## Step 2 — confirm the mismatch The winning version (nearest) is older than what some component needs. Check release notes / javadoc for when the missing method was added. ## Step 3 — fix (pick one) **Preferred: dependencyManagement** — forces a version everywhere, independent of depth: ```xml <dependencyManagement> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>libC</artifactId> <version>2.0</version> </dependency> </dependencies> </dependencyManagement> ``` **Direct declaration** — if you actually use libC, declaring it puts it at depth 1, where nearest-wins guarantees it. **Exclusion** — prune the path that drags in the bad version so the good path's version is used. ## Step 4 — verify ```bash mvn dependency:tree -Dincludes=com.example:libC mvn test ``` Confirm a single, correct version resolves and tests pass. ## Step 5 — prevent recurrence Add the enforcer convergence rule: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <executions><execution> <goals><goal>enforce</goal></goals> <configuration><rules><dependencyConvergence/></rules></configuration> </execution></executions> </plugin> ``` It fails the build when an artifact resolves to conflicting versions across the graph — catching the issue at build time instead of in production. BOM imports (`<scope>import</scope>` in dependencyManagement) keep families of artifacts aligned.

  • Why prefer dependencyManagement over an exclusion to fix this?
    dependencyManagement forces one version graph-wide regardless of depth and survives new paths appearing later; an exclusion only fixes the specific paths you remember to prune.
  • How do you stop this class of bug from recurring?
    Add the maven-enforcer-plugin dependencyConvergence rule to fail the build on divergent versions, and align artifact families with imported BOMs.
  • What's the difference between NoSuchMethodError and NoClassDefFoundError here?
    NoSuchMethodError means the class is present but a method is missing (version mismatch); NoClassDefFoundError means the class itself is absent at runtime (e.g. an over-aggressive exclusion or relocation).

saying these in an interview costs you the question

  • Reaching for an exclusion before checking dependency:tree to confirm which version actually won.
  • Assuming Maven will pick the newest compatible version automatically — it picks the nearest.
  • Fixing only one path with an exclusion when dependencyManagement would cover the whole graph.

context