class file has wrong version 61.0, should be 52.0 [Solved]

Fix class file has wrong version 61.0, should be 52.0 by building with JDK 17+ in Maven, Gradle, IntelliJ and Eclipse. Includes a class version table.

A Java 17 library with class file version 61 rejected by a Java 8 compiler that reads only up to version 52, and accepted by a JDK 17 or newer compiler

The compiler error “class file has wrong version 61.0, should be 52.0” means that a library on the classpath was compiled for Java 17 (class file version 61), but our code is compiled by a Java 8 JDK, which reads class files only up to version 52. The fix is to build the project with JDK 17 or newer, not to downgrade the library.

We see the error most often while migrating to Spring Boot 3 or 4, Spring Framework 6 or 7, Hibernate 7 or JUnit 6, because all of them ship Java 17 class files. The same message with “should be 55.0” means the compiler is JDK 11. The following example is the Maven fix for a Spring Boot project.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>4.1.1</version>
</parent>

<properties>
  <java.version>17</java.version>   <!-- or 21, 25 -->
</properties>

Notice that the pom.xml setting alone is not enough; Maven itself has to run on JDK 17 or newer, which mvn -v shows. We read the error message first, fix it in Maven, Gradle, IntelliJ IDEA and Eclipse, list all class file versions up to Java 27, and separate it from the runtime error with a similar message.

1. Why the Class File Has Wrong Version 61.0

The javac compiler reads the class files of every dependency to check our code against them. Each class file starts with a version number, and a JDK can read class files only up to its own version. When a dependency is newer than the JDK that runs javac, the compiler stops with a “bad class file” error.

For example, the baseline for Spring Framework 6 and Spring Boot 3 is Java 17, and Spring Boot 4 keeps that baseline. Compiling a Spring Boot 4.1.1 application with a Java 8 JDK prints the following error.

ShopApplication.java:1: error: cannot access SpringApplication
import org.springframework.boot.SpringApplication;
                               ^
  bad class file: /home/dev/.m2/repository/org/springframework/boot/spring-boot/4.1.1/spring-boot-4.1.1.jar(org/springframework/boot/SpringApplication.class)
    class file has wrong version 61.0, should be 52.0
    Please remove or make sure it appears in the correct subdirectory of the classpath.

The two numbers in the message answer two questions. The first number is the version of the library class, and the second number is the highest version that the running compiler understands.

Part of the messageMeaningExample
wrong version 61.0The library class was compiled for Java 17spring-boot-4.1.1.jar
should be 52.0The JDK running javac is Java 8JAVA_HOME points to JDK 8
should be 55.0The JDK running javac is Java 11An IDE or CI image still on JDK 11
A Java 17 library with class file version 61 rejected by a Java 8 compiler that reads only up to version 52, and accepted by a JDK 17 or newer compiler
The second number belongs to the JDK that runs javac; only a newer JDK makes the error go away

The “should be” number belongs to the compiler JDK, not to our –release or target setting. For example, JDK 25 compiling with –release 21 against a library built by JDK 27 still reports “wrong version 71.0, should be 69.0”. Changing the target level never fixes the error; changing the JDK does.

2. Fixing the Wrong Version Error

To fix the compilation issue, we compile the application with Java 17 or newer, and every tool that runs javac has to use that JDK. On a developer laptop that can mean three places at once, the terminal, the build tool and the IDE.

2.1. Check Which JDK Compiles the Code

Before changing any file, we find out which JDK each tool uses. The java -version command alone is not enough, because Maven and Gradle can use a different JDK through JAVA_HOME or their own settings.

javac -version
mvn -v                  # shows "Java version: ..." used by Maven
./gradlew -version      # shows the Launcher and Daemon JVM

Inside a running program, two system properties show the same information. The java.class.version property is the highest class file version the JVM accepts.

String javaVersion = System.getProperty("java.version");          // "25.0.4.1"
String maxClassVersion = System.getProperty("java.class.version"); // "69.0"
int feature = Runtime.version().feature();                         // 25

2.2. Maven

A Spring Boot project sets the Java level with the java.version property, as in the intro, because the Boot parent copies it into maven.compiler.release. A project without the Boot parent sets maven.compiler.release in its own properties. The release option is better than source and target, because it also checks that we use only APIs of that Java version.

<properties>
  <maven.compiler.release>17</maven.compiler.release>
</properties>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.16.0</version>
    </plugin>
  </plugins>
</build>

Next, we point JAVA_HOME to a JDK 17 or newer and run mvn -v again. If the JDK that runs Maven does not match the settings, the build fails in one of these ways.

  • With maven.compiler.source and target set to 17 on JDK 8, the build stops with Fatal error compiling: invalid target release: 17.
  • With maven.compiler.release set to 17 on JDK 8, the compiler plugin drops the flag, compiles Java 8 class files, and the dependency error from section 1 comes back.
  • With a release newer than the JDK, for example 27 on JDK 25, the build stops with error: release version 27 not supported.

2.3. Gradle

Gradle uses a Java toolchain to pick the JDK for compiling and testing, separate from the JVM that runs Gradle. With a toolchain, a laptop where JAVA_HOME points to an old JDK still compiles with the right one, and with the Foojay toolchain resolver plugin, Gradle downloads it if it is missing.

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

Older build files set only sourceCompatibility and targetCompatibility. Those settings behave like Maven’s source and target, so they do not change the JDK and do not fix the error.

2.4. IntelliJ IDEA and Eclipse

IDEs keep their own JDK settings, which explains why a project builds in the terminal and fails in the IDE, or the other way round. We change the project settings in the IDE as well.

  • In IntelliJ IDEA, set the SDK in File | Project Structure | Project to JDK 17 or newer, and set the language level to match.
  • For Maven projects in IntelliJ IDEA, also check the JRE in Settings | Build, Execution, Deployment | Build Tools | Maven | Runner; for Gradle projects, check Gradle JVM under Build Tools | Gradle.
  • In Eclipse, add a JDK 17 or newer under Window | Preferences | Java | Installed JREs, select it in the project’s Java Build Path, and set the compiler compliance level under Java Compiler.
  • After the change, reload the Maven or Gradle project so the IDE picks up the new settings.

After these changes, the compiler error is gone. On a CI server, the same check applies to the build image; a Docker image such as maven:3-eclipse-temurin-8 keeps failing until we move it to a JDK 17 or newer image.

3. Java Class File Versions

The class file major version is the Java release plus 44, so Java 17 is 61 and Java 25 is 69. The minor version is 0 for all releases since Java 12, except for classes compiled with preview features, which use 65535. Every release has its own major version number, from 45 for Java 1.1 to 71 for Java 27.

Java VersionClass File VersionJava VersionClass File Version
Java 1.0 and 1.145Java 1559.0
Java 1.246.0Java 1660.0
Java 1.347.0Java 17 (LTS)61.0
Java 1.448.0Java 1862.0
Java 549.0Java 1963.0
Java 650.0Java 2064.0
Java 751.0Java 21 (LTS)65.0
Java 8 (LTS)52.0Java 2266.0
Java 953.0Java 2367.0
Java 1054.0Java 2468.0
Java 11 (LTS)55.0Java 25 (LTS)69.0
Java 1256.0Java 2670.0
Java 1357.0Java 2771.0
Java 1458.0

The version number in the error message shows which JDK is used and which one is expected. To read the version of a class inside a jar, we run javap -v on it, as shown in viewing the bytecode of a class file.

javap -v -cp spring-boot-4.1.1.jar org.springframework.boot.SpringApplication | grep "major version"
  major version: 61

Several popular libraries moved to Java 17 class files in their current major versions, so a project that upgrades one of them meets this error first.

LibraryClass file versionMinimum Java
Spring Boot 3.x and 4.x, Spring Framework 6.x and 7.x6117
Hibernate ORM 76117
Apache Tomcat 116117
JUnit 66117

4. The Same Problem at Runtime

The compiler is not the only tool that checks the version. When a class compiled for a newer Java version is started on an older JVM, the program fails at runtime with UnsupportedClassVersionError, and the message uses the same numbers in a longer sentence.

Exception in thread "main" java.lang.UnsupportedClassVersionError: Hello has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0

The fix is the same, a newer JVM on the server or in the container image, or a lower release for our own code when we have to support an old runtime. A third message, “Unsupported class file major version 69”, comes from tools such as Gradle or bytecode libraries that are older than the JDK; it is covered in unsupported class file major version.

MessageThrown byMeans
class file has wrong version 61.0, should be 52.0javac (build time)A dependency is newer than the compiler JDK
UnsupportedClassVersionError … up to 52.0The JVM (run time)Our class or a dependency is newer than the JVM
Unsupported class file major version 69A tool or library (build or run time)The tool is older than the JDK it runs on

The class UnsupportedClassVersionError extends LinkageError, an unchecked Error, so no try-catch in our code can repair it. The hierarchy of errors and exceptions is explained in checked vs unchecked exceptions.

5. Class File Wrong Version FAQs

Several answers start from the same situation, a pom.xml that already says 17 while the build still fails.

5.1. Which Java version is class file version 61.0?

Java 17. The major version is the Java release plus 44, so 52 is Java 8, 55 is Java 11, 65 is Java 21 and 69 is Java 25.

5.2. I set Java 17 in pom.xml. Why does the error stay?

Because Maven or the IDE still runs an older JDK. The pom.xml settings control the target level, while the “should be” number comes from the JDK that runs javac. Run mvn -v, fix JAVA_HOME, and check the Maven Runner JRE in IntelliJ IDEA.

5.3. Can I use Spring Boot 3 or 4 with Java 8 or 11?

No. Spring Boot 3 and 4 need Java 17 or newer at compile time and at run time. A project that must stay on Java 8 or 11 has to stay on Spring Boot 2.7, which no longer receives open source updates.

5.4. Can I downgrade the library instead of upgrading the JDK?

Yes, if an older version of the library supports our Java version, for example JUnit 5 instead of JUnit 6. It is a short-term fix only, because the older versions stop getting security fixes.

5.5. Does the error appear with class file version 65.0 or 69.0 too?

Yes, the pattern is the same for every version. For example, “wrong version 65.0, should be 61.0” means a Java 21 library is compiled by JDK 17, and “wrong version 71.0, should be 69.0” means a Java 27 library is compiled by JDK 25.

6. Conclusion

The error “class file has wrong version 61.0, should be 52.0” tells us that a dependency was compiled for Java 17 and the compiler runs on Java 8. The fix is a JDK 17 or newer in every place that runs javac, namely the terminal, Maven or Gradle, the IDE and the CI image.

Setting maven.compiler.release, java.version or a Gradle toolchain declares the target, and mvn -v, javac -version and javap -v show which JDK runs. With the version table, any pair of numbers in the message maps to the JDK we have and the JDK we need.

7. References

Happy Learning !!

Source Code on Github

Leave a Comment

  1. It wasn’t gone!! How can you be so sure that if it worked for you, it will be for all others?

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.