The Lombok NoSuchFieldError for the field qualid of the class com.sun.tools.javac.tree.JCTree$JCImport means that we compile with JDK 21 or newer while the build still uses Lombok 1.18.28 or older, and we fix it by upgrading Lombok to 1.18.30 or later. The latest release today is Lombok 1.18.48, which supports every JDK up to JDK 27.
The Lombok NoSuchFieldError shows up right after a JDK upgrade, for example when a team moves a Spring Boot 3.1 service from Java 17 to Java 21. The code did not change, but every mvn compile or IntelliJ build stops with the error.
The following example is the fix in pom.xml. We set the new Lombok version in both places where Maven reads it.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.48</version> <!-- was 1.18.28 or older -->
<scope>provided</scope>
</dependency>
<!-- inside maven-compiler-plugin <configuration> -->
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.48</version> <!-- same version as the dependency -->
</path>
</annotationProcessorPaths>
Notice that the version appears twice. When we update only the dependency, the compiler plugin keeps loading the old Lombok from annotationProcessorPaths, and the error stays.
Next, we look at why a JDK upgrade breaks Lombok and which Lombok version each JDK needs. After that, we fix the error in Maven and Gradle builds, including Spring Boot projects, and check which Lombok version the build uses.
1. Why Lombok Fails With NoSuchFieldError on JDK 21
Lombok is an annotation processor, i.e. a plugin that runs inside the Java compiler (javac). It does not generate new source files. Instead, it changes the compiler’s internal tree of our code, called the Abstract Syntax Tree (AST), and adds the generated methods, such as getters and setters, there.
The AST classes, such as com.sun.tools.javac.tree.JCTree$JCImport, are part of the internal implementation of javac. They are not a public API, so the JDK team can change them in any release. Lombok reads and changes these internal classes with reflection, which works only as long as the fields have the names and types that Lombok expects.
In JDK 21, the field qualid of JCTree$JCImport, which holds the imported class name, changed its type from JCTree to JCFieldAccess.
public JCTree qualid; // Java 20 and before
public JCFieldAccess qualid; // Java 21 and later
Lombok 1.18.28 and older look for a field named qualid of type JCTree. The JVM finds no such field in JDK 21, so it throws NoSuchFieldError, and Maven reports it as a fatal compiler error.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile)
on project lombok-demo: Fatal error compiling: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport
does not have member field 'com.sun.tools.javac.tree.JCTree qualid' -> [Help 1]
In IntelliJ IDEA, the same error starts with java: java.lang.NoSuchFieldError, because the IDE runs the same javac with the same Lombok jar. The fix is the same in both cases, because Lombok 1.18.30 added support for JDK 21 and reads the new field type.
2. Minimum Lombok Version for Each JDK
Every new JDK changes some javac internals, so each JDK release needs a Lombok release that knows about the changes. The table lists the first Lombok version that supports each JDK.
| JDK | Minimum Lombok version | Released |
|---|---|---|
| 17 | 1.18.22 | October 2021 |
| 21 | 1.18.30 | September 2023 |
| 22 | 1.18.32 | March 2024 |
| 23 | 1.18.36 | November 2024 |
| 24 | 1.18.38 | March 2025 |
| 25 | 1.18.40 | September 2025 |
| 26 | 1.18.46 | April 2026 |
| 27 | 1.18.48 | September 2026 |
On a newer JDK, an old Lombok fails with a different message, because Lombok hits a different internal change first. For example, Lombok 1.18.36 and older stop on JDK 25 because the enum com.sun.tools.javac.code.TypeTag no longer has the constant UNKNOWN.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.16.0:compile (default-compile)
on project lombok-demo: Fatal error compiling: java.lang.ExceptionInInitializerError:
com.sun.tools.javac.code.TypeTag :: UNKNOWN -> [Help 1]
The recommendation is to always update to the latest version of Lombok, which supports all older JDKs too. So the next JDK upgrade needs only a Lombok version bump, not an investigation.
3. Fixing the Error in a Maven Project
In a Maven project, the Lombok version can come from more than one place, and the build fails as long as one of them still has the old version. We change the version wherever it is set.
- The lombok dependency in the dependencies section.
- The path entry in the annotationProcessorPaths of the maven-compiler-plugin.
- The parent POM, such as spring-boot-starter-parent, when the dependency has no version of its own.
3.1. Lombok Dependency and Annotation Processor Path
The following example is a complete build section for a project that compiles with JDK 25. It uses Lombok 1.18.48 and maven-compiler-plugin 3.16.0.
<properties>
<maven.compiler.release>25</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.48</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.16.0</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.48</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Do not forget to update the version in maven-compiler-plugin also if you have added it to the project. The provided scope keeps Lombok out of the final jar, because the generated methods are already in the compiled classes.
With the fix in place, the build passes, and the class annotated with @Data has its generated methods. For example, a Song class with the fields title and seconds prints its generated toString() output.
Song song = new Song();
song.setTitle("Yesterday");
song.setSeconds(125);
String text = song.toString(); // Song(title=Yesterday, seconds=125)
3.2. Spring Boot Projects
Spring Boot manages the Lombok version in spring-boot-dependencies, so a project with spring-boot-starter-parent often has no Lombok version in its own pom.xml. So the Lombok version depends on the Spring Boot version, and Spring Boot raises it in feature and patch releases.
| Spring Boot | Managed Lombok version | Works up to |
|---|---|---|
| 3.1.3 | 1.18.28 | JDK 20 |
| 3.1.4 | 1.18.30 | JDK 21 |
| 3.3.0 | 1.18.32 | JDK 22 |
| 3.4.0 | 1.18.36 | JDK 23 |
| 3.5.0 | 1.18.38 | JDK 24 |
| 3.5.6 | 1.18.40 | JDK 25 |
| 4.0.0 | 1.18.42 | JDK 25 |
| 4.1.1 | 1.18.46 | JDK 26 |
So a Spring Boot 3.1.3 application fails on JDK 21 even though nobody touched the Lombok dependency. We have two fixes. The better one is to upgrade Spring Boot, because the new version also brings fixes for the other libraries. When an upgrade is not possible right away, we override the managed version with the lombok.version property.
<properties>
<java.version>21</java.version>
<lombok.version>1.18.48</lombok.version> <!-- overrides the version from Spring Boot -->
</properties>
The property also changes the version in an annotationProcessorPaths entry without a version element, which is the setup that Spring Initializr generates for new projects. The maven-compiler-plugin 3.12.0 and later read the missing version from the dependency management of the parent.
4. Fixing the Error in Gradle
Gradle needs Lombok in two configurations. The compileOnly configuration lets our code see the annotations, and the annotationProcessor configuration lets javac run Lombok. Both must have the same version.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(25)
}
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.48'
annotationProcessor 'org.projectlombok:lombok:1.18.48'
testCompileOnly 'org.projectlombok:lombok:1.18.48'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.48'
}
The test configurations matter when test classes use Lombok annotations too, for example a test builder with @Builder.
5. Checking Which Lombok Version the Build Uses
When the error stays after the upgrade, the build still loads an old Lombok from somewhere else, such as a parent POM or a BOM. The Maven Dependency Plugin shows the version that Maven resolves.
mvn dependency:tree -Dincludes=org.projectlombok
For the Spring Boot 3.1.3 project from section 3.2, the tree shows the managed version before the fix and 1.18.48 after we set the lombok.version property.
[INFO] com.howtodoinjava:lombok-boot:jar:1.0
[INFO] \- org.projectlombok:lombok:jar:1.18.48:compile
For Gradle, the command gradle dependencies –configuration annotationProcessor lists the Lombok version that javac runs, e.g. org.projectlombok:lombok:1.18.48. In IntelliJ IDEA, we reload the Maven or Gradle project after changing the version, because the IDE keeps the old jar on the processor path until the next import.
6. Lombok NoSuchFieldError FAQs
6.1. Can We Fix the Error by Going Back to an Older JDK?
Yes, compiling with JDK 20 or older removes the error, because those JDKs still have the old qualid field. But it is a step back, since the project loses the new language features and the security updates. Upgrading Lombok is a one-line change and works on old and new JDKs.
6.2. Why Do We Get “cannot find symbol” for Getters After Upgrading to JDK 23 or Later?
Since JDK 23, javac no longer runs annotation processors that it only finds on the class path (JDK-8321314). When Lombok is only a dependency and not in annotationProcessorPaths, Lombok never runs, so the generated methods are missing.
[ERROR] /tmp/lombok-nopath/src/main/java/com/howtodoinjava/demo/Main.java:[6,9] cannot find symbol
[ERROR] symbol: method setTitle(java.lang.String)
[ERROR] location: variable song of type com.howtodoinjava.demo.Song
We fix it by adding Lombok to annotationProcessorPaths, as in section 3.1. The other option is to keep the old behavior with the property maven.compiler.proc set to full, e.g. mvn compile -Dmaven.compiler.proc=full.
6.3. Why Does Lombok Print a Warning About sun.misc.Unsafe on JDK 25?
The warning sun.misc.Unsafe::objectFieldOffset has been called by lombok.permit.Permit comes from JDK 24 and later, which warn about every use of the memory-access methods in sun.misc.Unsafe (JEP 498). It is a warning, not an error, so the build still passes and the classes are complete.
7. Conclusion
The NoSuchFieldError for JCTree$JCImport.qualid is a version mismatch between the JDK and Lombok. JDK 21 changed the type of an internal javac field, and Lombok 1.18.28 and older cannot read it.
We fix the error by upgrading Lombok to 1.18.30 or later, and the latest 1.18.48 also covers JDK 25 and newer. The version must change in the dependency and in annotationProcessorPaths, and in Spring Boot projects through a newer Spring Boot or the lombok.version property.
When the error stays, mvn dependency:tree shows which Lombok version the build resolves.
8. References
- Lombok changelog
- Lombok issue 3393: incompatible with JDK 21
- Lombok setup for Maven
- Lombok setup for Gradle
- JDK 23 release notes
- Apache Maven Compiler Plugin
Happy Learning !!