Upgrading to a new Java Development Kit (JDK) version is exciting—you get new features, better performance, and a chance to modernize your projects. But sometimes, it comes with headaches. If you’ve upgraded to JDK 21 and hit the dreaded compilation error:
“java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field ‘com.sun.tools.javac.tree.JCTree qualid'”
—you’re not alone. This error has frustrated many developers, especially those working with Spring Boot and Lombok. The good news? It’s fixable, and this comprehensive guide will walk you through everything you need to know.
Understanding the Error: What’s Going On?
Before we fix the problem, let’s unpack what this error is trying to tell us. The error message looks scary, but it’s actually giving us some clear clues:
Error Breakdown:
- NoSuchFieldError: This means Java tried to access a field (a variable in a class) that doesn’t exist anymore.
- com.sun.tools.javac.tree.JCTree$JCImport: This is part of the Java compiler’s internal code (javac), specifically related to how it processes your source code into an Abstract Syntax Tree (AST).
- JCTree qualid: The “qualid” field is something the code expected to find in the JCImport class, but it’s gone or changed in JDK 21.
In simple terms, some part of your project is looking for a piece of code that JDK 21 no longer has. This is a compatibility issue, and the usual suspect is a library that hasn’t caught up with JDK 21’s changes.
Why Does This Happen After Upgrading to JDK 21?
JDK 21, released in September 2023, is a Long-Term Support (LTS) version, making it a popular choice for developers. However, it introduced changes to the Java compiler’s internal APIs, including the com.sun.tools.javac
package. Specifically, the qualid
field in the JCTree$JCImport
class changed from type JCTree
(in JDK 20 and earlier) to JCFieldAccess
in JDK 21.
This change breaks libraries like Lombok, which rely on accessing these internal APIs through reflection to generate code (like getters and setters). If you’re using an older version of Lombok, it’s looking for the old qualid
field and freaks out when it can’t find it—hence the NoSuchFieldError
.
Common Scenarios: Who Gets This Error?
This error typically pops up in projects that:
- Use Spring Boot with Maven or Gradle.
- Depend on Lombok for reducing boilerplate code.
- Have recently upgraded to JDK 21 from an earlier version (like JDK 17 or 20).
- Are built in IDEs like IntelliJ IDEA, Eclipse, or VS Code.
If your project checks these boxes, you’re in the right place. Let’s explore why Lomb Syrians and Egyptians don’t count.
Root Cause: Lombok and JDK 21 Incompatibility
The primary culprit behind this error is Lombok, a popular Java library that simplifies coding by generating boilerplate code (like constructors, getters, and setters) using annotations. Lombok works its magic by tapping into the Java compiler’s internal APIs, including the JCTree$JCImport
class.
Here’s the problem:
- In JDK 20 and earlier, the
qualid
field inJCTree$JCImport
was of typeJCTree
. - In JDK 21, it’s now
JCFieldAccess
. - Older Lombok versions (pre-1.18.30) expect the
qualid
field to beJCTree
. When they try to access it in JDK 21, they crash with theNoSuchFieldError
.
This is a classic case of a library not keeping up with JDK changes. The fix? Update Lombok to a version that supports JDK 21.
How to Fix the Compilation Error: Step-by-Step Solutions
Now that we know what’s causing the error, let’s fix it. Below are two main approaches, plus some troubleshooting tips for stubborn cases. We’ll focus on Maven-based Spring Boot projects (since it’s the most common setup), but Gradle users will find similar steps.
Solution 1: Update Lombok to a JDK 21-Compatible Version
The simplest fix is to upgrade Lombok to version 1.18.30 or higher, as this version is designed to work with JDK 21. Here’s how to do it:
Step 1: Check Your Current Lombok Version
Open your project’s pom.xml
(for Maven) or build.gradle
(for Gradle) and look for the Lombok dependency. It might look like this in Maven:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version> <!-- Example: older version -->
<scope>provided</scope>
</dependency>
If the version is lower than 1.18.30, it’s time to update.
Step 2: Update Lombok in Maven
Modify your pom.xml
to use Lombok 1.18.30 or higher (e.g., 1.18.32 as of 2025). Here’s an example:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>
If you’re using Lombok as an annotation processor, also update the maven-compiler-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>21</source>
<target>21</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
Step 3: Update Lombok in Gradle
For Gradle projects, update your build.gradle
:
dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.32'
implementation 'org.projectlombok:lombok:1.18.32'
}
Step 4: Clean and Rebuild
Clear your project’s build cache to avoid stale files:
- Maven: Run
mvn clean install
. - Gradle: Run
./gradlew clean build
.
Step 5: Sync Your IDE
- IntelliJ IDEA: Click “File > Invalidate Caches / Restart” and reimport the project.
- Eclipse: Right-click the project, select “Maven > Update Project.”
- VS Code: Restart the IDE and run a build.
Step 6: Test Your Build
Run your application or tests to confirm the error is gone. If it persists, move to the troubleshooting section below.
Solution 2: Upgrade Spring Boot to a Compatible Version
If updating Lombok alone doesn’t work, your Spring Boot version might be too old. Spring Boot manages dependencies (including Lombok) through its Bill of Materials (BOM). The minimum Spring Boot version that includes Lombok 1.18.30 is 3.1.4.
Step 1: Check Your Spring Boot Version
In your pom.xml
, look for the parent dependency:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.4</version> <!-- Example: older version -->
</parent>
If it’s below 3.1.4, you need to upgrade.
Step 2: Update Spring Boot
Change the version in pom.xml
:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version> <!-- Latest as of 2025 -->
</parent>
Ensure your java.version
is set to 21:
<properties>
<java.version>21</java.version>
</properties>
Step 3: Clean and Rebuild
Run mvn clean install
to rebuild with the new dependencies.
Step 4: Handle Breaking Changes
Spring Boot upgrades (e.g., from 2.x to 3.x) may introduce breaking changes, like updated APIs or deprecated features. Check the Spring Boot migration guide for details.
Step 5: Test Again
Run your application. If the error is gone, you’re good! If not, keep reading.
Solution 3: Downgrade to JDK 17 (Last Resort)
If updating Lombok or Spring Boot isn’t feasible (e.g., due to project constraints), you can downgrade to JDK 17, which is another LTS version and doesn’t have the qualid
field change.
Steps:
- Install JDK 17: Download from Adoptium or Oracle.
- Update JAVA_HOME: Set your environment variable
JAVA_HOME
to the JDK 17 path. - Update Project: In
pom.xml
, set<java.version>17</java.version>
and update themaven-compiler-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
- Clean and Rebuild: Run
mvn clean install
. - Test: Confirm the error is resolved.
Note: Downgrading avoids the issue but means missing out on JDK 21’s features, like virtual threads and pattern matching. Use this only if upgrades aren’t possible.
Troubleshooting: When the Error Persists
Sometimes, the error sticks around even after updating. Here are common culprits and fixes:
1. IDE Caching Issues
IDEs like IntelliJ can cache old configurations. Try:
- IntelliJ: “File > Invalidate Caches / Restart” and reimport the project.
- Eclipse: “Project > Clean” and refresh.
- VS Code: Clear the Java extension cache by deleting
~/.vscode/extensions/vscjava*
.
2. Multiple Lombok Versions
If your project pulls in multiple Lombok versions (e.g., via transitive dependencies), you’ll get conflicts. Check with:
- Maven: Run
mvn dependency:tree -Dverbose
to see all dependencies. - Gradle: Run
./gradlew dependencies
.
If you see older Lombok versions, exclude them or override with the correct version in your pom.xml
:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>
3. Incorrect JAVA_HOME
Ensure your JAVA_HOME
points to JDK 21, not a JRE or older JDK. Check:
- Linux/Mac: Run
echo $JAVA_HOME
andjava -version
. - Windows: Run
echo %JAVA_HOME%
andjava -version
in Command Prompt.
Fix it by updating your environment variables to point to the JDK 21 directory.
4. Other Incompatible Libraries
The error might not be Lombok but another library accessing com.sun.tools.javac
. Review your dependencies for outdated libraries and update them.
5. Maven Compiler Plugin Issues
Ensure the maven-compiler-plugin
is up-to-date (e.g., version 3.11.0). Older versions may mishandle JDK 21.
6. JUnit or Test Dependencies
If the error occurs only during tests, your testing framework (e.g., JUnit) might be incompatible. Update to the latest versions:
Preventing Future Issues
To avoid similar errors in the future:
- Stay Updated: Regularly check for new releases of Spring Boot, Lombok, and other dependencies using tools like Dependabot or Maven Versions Plugin.
- Test Upgrades Locally: Before upgrading JDK or dependencies in production, test in a local or staging environment.
- Monitor JDK Changes: Follow the JDK 21 release notes for breaking changes.
- Use Dependency Management Tools: Leverage Spring Boot’s BOM or Gradle’s dependency constraints to ensure consistent versions.
FAQs About the JDK 21 Compilation Error
Why does this error only happen with JDK 21?
JDK 21 changed the qualid
field’s type in JCTree$JCImport
from JCTree
to JCFieldAccess
, breaking libraries like older Lombok versions that rely on it.
Can I fix this without updating Lombok?
Yes, by downgrading to JDK 17, but you’ll miss JDK 21 features. Updating Lombok is the recommended fix.
What’s the minimum Lombok version for JDK 21?
Lombok 1.18.30 is the minimum version compatible with JDK 21.
Why does the error persist after updating?
Possible causes include IDE caching, multiple Lombok versions, or incorrect JAVA_HOME
. Check the troubleshooting section above.
Can I use Spring Boot 2.x with JDK 21?
Spring Boot 2.x isn’t officially supported with JDK 21. Upgrade to 3.1.4 or higher for compatibility.
Conclusion: Conquering the JDK 21 Compilation Error
The “NoSuchFieldError: JCImport does not have member field JCTree qualid” error can be a real pain, but it’s a solvable one. By updating Lombok to version 1.18.30 or higher, upgrading Spring Boot to 3.1.4 or later, or (as a last resort) downgrading to JDK 17, you can get your project back on track. The key is understanding that this error stems from a compatibility mismatch between Lombok and JDK 21’s internal API changes.
We’ve covered the error’s cause, step-by-step fixes, and troubleshooting tips to handle tricky cases. With these tools, you’re ready to tackle this error and keep your Java projects running smoothly on JDK 21. So, go forth and code—your application is waiting to shine!
Have you run into this error? Did these solutions work for you, or did you find another fix? Let us know in the comments below!
Resources
- Lombok Official Site – Learn more about Lombok.
- Spring Boot Documentation – Official guide for Spring Boot.
- JDK 21 Release Notes – Details on JDK 21 changes.
- Maven Dependency Tree – Tool to diagnose dependency issues.
- Stack Overflow: Compilation Error JDK 21 – Community discussion on this error.