Java "UnsupportedClassVersionError" in CI - Runtime JDK Too Old
A class was compiled by a newer JDK than the JRE now trying to run it. The runtime reads the class-file version, sees it is from the future, and refuses to load it.
What this error means
The application or test launch fails immediately with UnsupportedClassVersionError, naming the class-file major version it found vs the maximum the runtime supports (e.g. 65.0 = Java 21, runtime supports up to 61.0 = Java 17).
Exception in thread "main" java.lang.UnsupportedClassVersionError:
com/example/App has been compiled by a more recent version of the Java
Runtime (class file version 65.0), this version of the Java Runtime only
recognizes class file versions up to 61.0Common causes
Runtime JDK older than the compile JDK
The build compiled with JDK 21 (class version 65) but the deploy/test stage runs on JDK 17 (max 61). The older runtime cannot load the newer bytecode.
Mismatched JDKs across pipeline stages
Build and run stages use different setup-java versions or different base images, so the bytecode target outpaces the runtime.
How to fix it
Run on a JDK at least as new as the compile JDK
Provision the runtime JDK to match or exceed the version used to compile.
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21' # runtime >= compile versionOr lower the bytecode target
If the runtime must stay on an older JDK, compile to that target with --release.
# Maven
<maven.compiler.release>17</maven.compiler.release>
# Gradle
# java { toolchain { languageVersion = JavaLanguageVersion.of(17) } }How to prevent it
- Use the same JDK version for build and run stages, or run on one >= the compile target.
- Pin
--releaseto your true minimum runtime. - Assert the JDK version at the start of each pipeline stage.