Java "java.lang.VerifyError" in CI - Fix Corrupt or Mismatched Bytecode
VerifyError means the JVM bytecode verifier found a class that violates the verification rules - bad operand types, inconsistent stack-map frames, or invalid structure. The class is malformed for the target JVM, typically due to old tooling or aggressive instrumentation.
What this error means
A class fails to load with java.lang.VerifyError: Bad type on operand stack or Inconsistent stackmap frames. It often appears after adding bytecode-manipulating libraries (ASM, agents, mocking) or running on a newer JVM than the tooling supports.
java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location: com/example/Proxy.invoke(...)Ljava/lang/Object; @12: invokevirtual
Reason: Type 'java/lang/Object' is not assignable to 'com/example/Service'Common causes
Outdated bytecode library for the running JDK
ASM/cglib/ByteBuddy versions too old to emit valid stack-map frames for the current class-file version produce classes the verifier rejects.
Stale or partially compiled classes
A leftover class from a previous incompatible build, or a corrupt jar, can fail verification on load.
How to fix it
Upgrade the bytecode tooling
Bump ASM/ByteBuddy/cglib (often via Mockito/Hibernate updates) to versions that support your JDK.
# Gradle: force a current ASM that knows the new class file format
dependencies {
implementation 'net.bytebuddy:byte-buddy:1.14.18'
}
configurations.all {
resolutionStrategy.force 'org.ow2.asm:asm:9.7'
}Clean and rebuild
- Run a clean build (
mvn clean/gradle clean) to remove stale incompatible classes. - If an agent is attached (coverage, APM), update or temporarily disable it to confirm it is the source.
- Map the class-file version in the error to your JDK and align the tooling.
How to prevent it
- Keep bytecode libraries and instrumentation agents current with the JDK, and always clean between JDK upgrades so no stale classes survive.