Java
JDK 21
Compilation Error
NoSuchFieldError
JCImport

Compilation error after upgrading to JDK 21 - NoSuchFieldError JCImport does not have member field JCTree qualid

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The NoSuchFieldError: JCImport does not have member field JCTree qualid error occurs because JDK 21 refactored the internal com.sun.tools.javac.tree.JCTree AST classes. Specifically, JCImport.qualid was replaced with a new accessor method as part of JEP 441/pattern-matching changes. The fix is almost always to upgrade Lombok, Mapstruct, Error Prone, or whichever annotation processor or compiler plugin is accessing that internal field.

What Changed in JDK 21

The com.sun.tools.javac.tree package is the internal Abstract Syntax Tree representation used by javac. These classes are not part of the public Java SE API. They live in the jdk.compiler module and are subject to change without notice between JDK releases.

In JDK 21, the JCImport node was restructured:

java
1// JDK 17-20 (old structure)
2public class JCImport extends JCTree {
3    public JCTree qualid;      // the imported name
4    public boolean staticImport;
5}
6
7// JDK 21+ (new structure)
8public class JCImport extends JCTree {
9    // 'qualid' field removed, replaced with accessor
10    public JCTree getQualifiedIdentifier() { ... }
11    public boolean isStatic() { ... }
12}

Any library that accessed jcImport.qualid directly via reflection or bytecode manipulation will throw NoSuchFieldError at compile time or runtime on JDK 21.

Which Libraries Are Affected

The most commonly affected libraries:

LibraryAffected VersionsFixed VersionNotes
Lombok< 1.18.301.18.30+Most common cause of this error
MapStruct< 1.5.51.5.5+Annotation processor
Error Prone< 2.23.02.23.0+Google's static analysis tool
Checker Framework< 3.39.03.39.0+Type-checking annotation processor
Immutables< 2.10.02.10.0+Code generation library
OpenJDK Nashorn< 15.415.4+JavaScript engine

Fix: Upgrade the Offending Library

Identifying Which Library Causes the Error

The stack trace tells you which library is accessing the internal API. Look for the class name right before the NoSuchFieldError:

 
java.lang.NoSuchFieldError: qualid
    at lombok.javac.handlers.HandleBuilder.handleAnnotation(HandleBuilder.java:...)
    at lombok.javac.JavacAnnotationHandler.handle(...)

In this example, Lombok is the culprit.

Fix for Lombok (Most Common)

Maven:

xml
1<dependency>
2    <groupId>org.projectlombok</groupId>
3    <artifactId>lombok</artifactId>
4    <version>1.18.34</version>
5    <scope>provided</scope>
6</dependency>

Gradle (Kotlin DSL):

kotlin
1dependencies {
2    compileOnly("org.projectlombok:lombok:1.18.34")
3    annotationProcessor("org.projectlombok:lombok:1.18.34")
4}

Gradle (Groovy DSL):

groovy
1dependencies {
2    compileOnly 'org.projectlombok:lombok:1.18.34'
3    annotationProcessor 'org.projectlombok:lombok:1.18.34'
4}

Fix for MapStruct

xml
1<dependency>
2    <groupId>org.mapstruct</groupId>
3    <artifactId>mapstruct-processor</artifactId>
4    <version>1.5.5.Final</version>
5    <scope>provided</scope>
6</dependency>

Fix for Error Prone

xml
1<plugin>
2    <groupId>org.apache.maven.plugins</groupId>
3    <artifactId>maven-compiler-plugin</artifactId>
4    <configuration>
5        <annotationProcessorPaths>
6            <path>
7                <groupId>com.google.errorprone</groupId>
8                <artifactId>error_prone_core</artifactId>
9                <version>2.28.0</version>
10            </path>
11        </annotationProcessorPaths>
12    </configuration>
13</plugin>

Diagnosing in Multi-Module Projects

In large projects with many dependencies, multiple libraries may access javac internals. Use this approach to find all potentially affected dependencies:

bash
1# Search for any dependency that references com.sun.tools.javac
2# in a Maven project
3mvn dependency:tree | grep -i "lombok\|mapstruct\|errorprone\|checker"
4
5# Or check the full dependency tree for version conflicts
6mvn dependency:tree -Dverbose

For Gradle:

bash
gradle dependencies --configuration compileClasspath | grep -i "lombok\|mapstruct"

If You Cannot Upgrade the Library

In rare cases, the library may not yet have a JDK 21-compatible release. Options:

Option 1: Pin JDK Version

Stay on JDK 17 or 20 until the library publishes a fix. Use a .sdkmanrc or toolchains.xml to enforce this:

xml
1<!-- Maven toolchains.xml -->
2<toolchains>
3    <toolchain>
4        <type>jdk</type>
5        <provides>
6            <version>17</version>
7        </provides>
8        <configuration>
9            <jdkHome>/path/to/jdk-17</jdkHome>
10        </configuration>
11    </toolchain>
12</toolchains>

Option 2: Add JVM Flags to Open Internal Modules

Some libraries work if you explicitly open the jdk.compiler module. Add these to your build:

bash
1--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
2--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
3--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
4--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

In Maven:

xml
1<plugin>
2    <groupId>org.apache.maven.plugins</groupId>
3    <artifactId>maven-compiler-plugin</artifactId>
4    <configuration>
5        <compilerArgs>
6            <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
7        </compilerArgs>
8    </configuration>
9</plugin>

This may suppress the IllegalAccessError but will not fix NoSuchFieldError since the field genuinely does not exist. This workaround only helps if the issue is access restriction, not a missing field.

Option 3: Fork and Patch

If the library is open source and unmaintained, fork the repository, update the internal API calls, and publish to your local Maven repository. This is a last resort.

Preventing This in Future JDK Upgrades

The root cause is dependency on internal com.sun.* APIs. To avoid this pattern:

  1. Audit dependencies before upgrading. Run your build against the new JDK in CI before committing to the upgrade.
  2. Subscribe to library release notes. Lombok, MapStruct, and Error Prone all publish JDK compatibility matrices in their documentation.
  3. Check jdeps for internal API usage. The jdeps tool can identify dependencies on internal APIs:
bash
jdeps --jdk-internals -cp your-app.jar
  1. Adopt JDK LTS releases conservatively. JDK 21 is an LTS release. Library maintainers typically prioritize LTS compatibility, so waiting 2-3 months after an LTS release gives most libraries time to update.

Common Pitfalls

  • Upgrading JDK without upgrading annotation processors. The JDK and annotation processor versions must be compatible. Always check the compatibility matrix before upgrading.
  • Transitive dependency pulling in an old version. You may have Lombok 1.18.34 in your POM, but a transitive dependency forces an older version. Use mvn dependency:tree or gradle dependencies to verify the resolved version.
  • IDE using a different JDK than the build. IntelliJ or Eclipse may compile with a different JDK than Maven/Gradle. Ensure IDE project SDK matches the build tool configuration.
  • Confusing NoSuchFieldError with NoSuchMethodError. Both indicate internal API changes, but the fix is the same: upgrade the library.
  • Using --add-opens as a permanent fix. Module-opening flags are a band-aid. They do not fix missing fields and they weaken the module system's encapsulation guarantees. Always prefer upgrading the library.

Summary

  • The NoSuchFieldError: JCImport does not have member field JCTree qualid error is caused by JDK 21 removing the qualid field from javac's internal AST classes.
  • The fix is to upgrade the annotation processor or compiler plugin that accesses this field. Lombok >= 1.18.30 and MapStruct >= 1.5.5 include the fix.
  • Use mvn dependency:tree or gradle dependencies to identify the exact library and version causing the error.
  • Do not rely on --add-opens JVM flags as a permanent solution. They cannot restore a field that no longer exists.
  • Before future JDK upgrades, audit your dependencies with jdeps --jdk-internals and check library compatibility matrices.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions