After a routine Spring Boot dependency upgrade, one service started failing at deploy time with APPLICATION FAILED TO START and a NoSuchMethodError from BouncyCastle. The build was green and the tests passed. It only broke once the app actually ran. The cause was a classic transitive-dependency conflict: two libraries pulled in the same BouncyCastle artifact at different versions, and Maven’s nearest-wins resolution kept the wrong (older) one. The fix was a one-line dependency exclusion.
The Symptom: Runtime NoSuchMethodError at Startup
Everything compiled, unit tests were green, the artifact built and the container image was published. Then the deployment step hung and eventually failed, the pod never became ready and the rollout timed out.
In scope of the application logs I’ve found:
An attempt was made to call a method that does not exist:
'void org.bouncycastle.util.BigIntegers.writeUnsignedByteArray(
java.io.OutputStream, java.math.BigInteger)'
The calling class, org.bouncycastle.bcpg.MPInteger,
was loaded from bcpg-jdk18on-1.84.jar
The called class, org.bouncycastle.util.BigIntegers,
was loaded from bcprov-jdk18on-1.80.2.jar
A NoSuchMethodError at startup. It was not a compile error but a runtime linkage error.
Why the build never caught it
What makes this issue tricky is that a NoSuchMethodError doesn’t show up until the JVM tries to call the missing method at runtime. And the bad call wasn’t even in our code, it was happening inside BouncyCastle, where the bcpg module was calling into an incompatible version of bcprov.
That’s why the build passed without any warnings. The compiler checks our code against the APIs provided by our dependencies, but it doesn’t confirm that every third-party library is compatible with every other library on the final classpath. Maven simply bundled the mismatched BouncyCastle modules and moved on.
The unit tests missed it for the same reason: none of them hit the exact code path that made the failing call. We only discovered the problem when the deployed application ran that path for the first time, during startup in the container.
Root Cause: Maven Classpath Version Mismatch
BouncyCastle ships as several modules that are really one library split up:
bcprov-jdk18on: the provider: the actual crypto engine.bcpg-jdk18on: the OpenPGP layer, built on top ofbcprov. It has no crypto of its own; it calls down intobcprov
These two must be the same version. bcpg 1.84 calls a method that only exists in bcprov 1.84.
The dependency upgrade left the classpath with bcpg, bcpkix, and bcutil at 1.84, but bcprov at 1.80.2. Why? Because bcprov was being pulled in from two different places in the tree, at two different versions:
service
├─ (feature library) ─▶ … ─▶ bcpg-jdk18on 1.84 ─▶ bcprov-jdk18on 1.84 (deep in the tree)
└─ spring-cloud-starter-openfeign ─▶ … ─▶ bcprov-jdk18on 1.80.2 (closer to the root)
Maven can only keep one version of an artifact on the classpath, so it applies “nearest-wins” mediation: the version closest to the root of the dependency tree wins. The OpenFeign path was shallower, so Maven kept bcprov 1.80.2 and discarded the 1.84 requested deeper down.
Result: bcpg 1.84 running on top of bcprov 1.80.2 → the method it needs isn’t there → NoSuchMethodError the first time the OpenPGP code executed at startup.
Key insight: a version mismatch alone isn’t automatically fatal. It became fatal here because the two versions were API-incompatible; bcpg 1.84 depends on a method introduced in bcprov 1.84.
The Fix: Resolve BouncyCastle Version Conflicts in Pom.xml
Exclude the older, conflicting bcprov-jdk18on from the dependency that dragged it in, so Maven no longer sees the 1.80.2 candidate and resolves bcprov to the 1.84 that comes in alongside bcpg:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</exclusion>
</exclusions>
</dependency>
An equally valid alternative is to pin the version explicitly in dependencyManagement:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.84</version>
</dependency>
</dependencies>
</dependencyManagement>
Important: excluding bcprov from OpenFeign does not remove it from the app. It’s still required and still pulled in transitively alongside bcpg, now at the matching 1.84. The exclusion only eliminates the conflicting older copy so the correct version wins. With all BouncyCastle artifacts aligned at 1.84, the NoSuchMethodError disappears and the service starts normally.




