Java — NoSuchMethodError at runtime after a dependency change
Fix NoSuchMethodError by detecting duplicate dependency versions causing the wrong class to load.
Symptoms
- java.lang.NoSuchMethodError: some.Class.method(...)
- The code compiled fine but fails at runtime
- The error appears after upgrading one library
- A method exists in source but not in the loaded jar
Possible causes
- Two versions of the same library are on the classpath and the older one wins
- An indirect dependency pins an older version
- A shaded or relocated jar contains a conflicting class
- The runtime classpath differs from the compile classpath
Diagnosis steps
Inspect the dependency tree
mvn dependency:tree -Dincludes=group:artifactInterpretation
Multiple versions of the artifact reveal the conflict that lets an older class shadow the new one.
Ask where the class came from
java -verbose:class -cp app.jar Main 2>&1 | grep SomeClassInterpretation
The loaded-from line names the jar providing the class, which is often not the version you expect.
Force a single version
mvn dependency:tree -Dverbose -Dincludes=group:artifactInterpretation
Understanding the paths lets you exclude or pin one version so only the intended jar loads.
Root cause
The class loaded at runtime came from a different version of the library than the one compiled against, so a method that exists in source is absent in the loaded class.
Fix
Resolve the version conflict by excluding the unwanted transitive version or pinning one version in dependency management, then rebuild so compile and runtime classpaths agree.
Verify the fix
Run the application and confirm the method resolves, then inspect the dependency tree to confirm a single version of the library remains.
Symptom walkthrough
An application compiled successfully throws NoSuchMethodError at runtime, naming a method the source clearly calls. The method exists in one version of a library and not in another, and the runtime loaded the wrong jar because two versions ended up on the classpath. This is a classpath conflict, not a code error, so editing the calling code will not help.
Fix in practice
Inspect the dependency tree for duplicate versions, exclude or pin the unwanted transitive dependency, and rebuild so the compile and runtime classpaths match. Verify the class source with verbose class loading when the conflict is indirect or shaded.
Verification
Rerun the application and confirm the call resolves, then re-inspect the dependency tree to confirm only one version remains. A single resolved version plus a working call confirms the fix. A dependency convergence rule in the build prevents the same conflict from returning unnoticed.
Diagnostic commands
Check the behavior with commands like these:
mvn dependency:tree -Dincludes=group:artifact
java -verbose:class -cp app.jar Main 2>&1 | grep SomeClass
mvn dependency:tree -Dverbose -Dincludes=group:artifact