Compilation error after upgrading to JDK 21 - "NoSuchFieldError: JCImport does not have member field JCTree qualid"
Asked Answered
S

10

210

After upgrading to JDK 21, I have the following compilation error in my Spring Boot project:

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'
Stat answered 25/9, 2023 at 9:5 Comment(3)
@PeterMortensen Well, at least 70 people understood what the question is, and at least 113 people appreciated the answer :) Isn't the question clear enough from the context, or do you want to be so formalistic as to require a sentence with a question mark?Stat
Why would not you add the question (even if it is obvious apparently) rather than write a lengthy comment here ?Sardanapalus
@ᐅdevrimbaris Actual behaviour: "Fatal error". Expected behaviour: "No error". Question: "How to get rid of the error?" Is it clear now? And no, I am not going to modify the text, it seems like most readers actually do understand it. And furthermore, when I wrote my questions I had already planned to add my own answer. I wanted to share the result of my effort with others who might have suffered from the same issue. As you can see from the upvotes, many people indeed have faced the very same problem and fully understood it even without a question-mark-adorned sentence.Stat
S
336

The culprit is Lombok. The minimal Lombok version compatible with JDK 21 is 1.18.30.

This implies that the minimal Spring Boot version is 3.1.4, unless you want to meddle with the Spring Boot autoconfiguration and set the Lombok version in your project differently from the Spring Boot BOM defined in spring-boot-dependencies.

See: [BUG] Lombok 1.8.26 incompatible with JDK 21 #3393

Stat answered 25/9, 2023 at 9:5 Comment(9)
No it doesn't imply the minimum boot version is 3.1.4 you can manually upgrade Lombok if you like (I just compiled Spring Boot 2.7.x version with a newer lombok version). But if you want certain Java21 for the whole spectrum (as that is tested with Java21) then 3.1.4 is indeed the version.Mercantilism
@M.Deinum Technically you are right, however I prefer not to meddle with autoconfigured dependency versions in Spring Boot, unless there is a really very good reason. It often brings more mess somewhere else unexpected. And always someone forgets this in the maven pom file and it causes problems later.Stat
Which I can only concur with, but it isn't the only option. Also lombok is a bit of a different beast for which you sometimes need to have another versions (although I would rather see that particular library not used at all but that is personal preference).Mercantilism
@M.Deinum I updated my answer accordingly :)Stat
Also, restart your IntelliJ IDERattletrap
This explains the cause of the issue, but how do you resolve it?Stace
@HonzaZidek Yes, I was serious which is why I wrote https://mcmap.net/q/126462/-compilation-error-after-upgrading-to-jdk-21-quot-nosuchfielderror-jcimport-does-not-have-member-field-jctree-qualid-quotStace
@DanielKaplan I resolved the "minimum version required is..." issue by simply upgrading my dependencies so I fulfil the requirement. In my projects I could do it just by upgrading to Spring Boot >= 3.1.4. Others who are not so lucky and have to keep their Spring Boot version lower, overrode their dependency and added Lombok >= 1.18.30. "How to manage Maven dependency" is another topic and as such has been answered in StackOverflow multiple times, so I guess that in the case of this particular error pointing out the root cause is enough for the answer :)Stat
Thank you for this. I had Lombok 1.18.30 but Spring Boot was still set at 3.1.1 in the POM. Upgrading to SB 3.1.4 solved the problem.Advancement
G
21

I followed the first answer from here and I made the following changes. Previously, it brought the Lombok version 1.18.20 as default, and I needed to feed the latest which resolved the issue for me when I moved from Spring Boot 2.XX to 3.3.3.

When doing a mvn dependency:tree, you can see from where the lower version is coming from and if you want exclude that and new or just add new and check one more time. Still it's pulling the older version. If not, just add a new one like below. So far there isn't any issue with this solution.

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>
Gilud answered 27/9, 2023 at 11:46 Comment(4)
It's a workaround - generally it's better not to meddle with the Spring Boot autoconfigured versions. It often brings more damage than benefit.Stat
@HonzaZidek we dont need to exclude it, its not worked initially i dont know why but when i purge the local repository and tried everything looks okGilud
@HonzaZidek - do you have a fix for the issue mate ? technical aspect might not always the answer. for us we have no issue so far after this fix. I cant see this as a work around. Its a fix for us. We have migrated all our old projects to 3.X.X with this in pomGilud
Sorry, Arundev, I don't understand your problem. Maybe create a question and describe it better?Stat
S
8

When I received this error, my pom.xml looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!-- ... -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- ... -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

I modified it to look like this, and the error went away:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!-- ... -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- ... -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <!-- <optional/> Removed -->
            <version>1.18.30</version> <!-- Added -->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

I found the answer in this GitHub comment, and you can find more background information there, too. Another user states this is a workaround, not a solution, but I haven't dug into it deep enough to form my own opinion.


I'm throwing my own answer into the ring because I feel it's more comprehensive than the others: It shows more of the pom.xml. Others include an excerpt of the pom.xml and assume the rest of it looks a specific way.

For example, one answer tells you to add a version number to lombok without telling you to exclude it from spring-boot-maven-plugin. Another answer has the opposite problem.

Stace answered 14/2 at 1:1 Comment(4)
Yes, lombok's version 1.18.30 is needed for JDK 21.Smoking
You don't show what your other dependencies' versions are, namely Sprint Boot. If you used Sprint Boot 3.1.4+, your lombok-related magic would not be necessary. Based on my experience, whenever I meddled with transitively dependent artefact, it backfired badly sometime in future. Imagine a situation like this: you have Sprint Boot 3.0, you meddle with Lombok version, later you upgrade SB to some future version 4.0, which depends on Lombok 2, but your code is still dependent on Lombok 1.18.30.Stat
@HonzaZidek You don't show what your other dependencies' versions are, namely Sprint Boot. Good point. I've included that in an edit. For context, this pom.xml was not created by me which is why I'm using such an old version. ...whenever I meddled with transitively dependent artefact, it backfired badly... I agree it's not ideal. Personally, it's never caused a huge issue when I run into those scenarios. Maybe I'm lucky, but they have been pretty easy to troubleshoot. Plus, in the context of this pom.xml, upgrading SB from 2.0 to 3.0 might be a project in it of itself.Stace
Thanks this worked , in addition I had to install Lombok plugin in the intellij idea.Ironsides
E
3

Use the Lombok exclude in the Spring Boot Maven plugin and it should work for JDK 21.

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <excludes>
                <exclude>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                </exclude>
            </excludes>
        </configuration>
    </plugin>

</plugins>
Eulalia answered 10/11, 2023 at 2:25 Comment(4)
I strongly do not recommend meddling with the Spring auto-configured dependencies, unless you really have a very good reason for it, like a temporary reason not to upgrade Spring Boot yer. I have seen more problems than benefits as a consequence of this approach.Stat
@HonzaZidek this is common pattern to exclude lombok from packaging dependencies because lombok needs only in compile time.Opportune
@Opportune You don't have to do it at all. The less you meddle with Spring Boot autoconfig, the better, unless you really need it. If you need to use the lombok classes of your project, all you need is to use <scope>provided</scope> . Lombok is properly configured in Spring Boot and is not included in your project in runtime. Not each "common pattern" is a good patter.Stat
@HonzaZidek Better check start.spring.io and create a project with Lombok dependency. And this official tool generates pom.xml with lombok exclude. You should check official documentation before blame others.Opportune
G
3

I also had today this problem after changing from Java 19 -> 21.

I also upgraded Spring boot version from 3.0.4 -> 3.2.3

I followed recommended approach to only increase lombok version to 1.18.30. Then error disapeared but I had issues with beans and dependencies so I returned spring boot version back to 3.0.4 and all works fine with java 21 and lombok.

I also tried to test which version of spring boot is making problem so I went from 3.0.4 to 3.2.2 and 3.1.8 is fine but from 3.2.2 is making problems with dependencies. I am using webflux from project reactor, so I will now stick with 3.1.8.

So there is also probably some change in last spring boot release that causes compatible issues with lombok I guess. I followed this article https://1kevinson.com/nosuchfielderror-jcimport-does-not-have-member-field-jctree-qualid/ below I cut how I have it in my pom.xml, I use Maven.

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.4</version>
        <relativePath/> <!-- lookup parent from repository -->
 </parent>
.....
<properties>
        <java.version>21</java.version>
</properties>
.....
<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.18.30</version>
            <scope>provided</scope>
</dependency>
...

<plugin>
              <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.project-lombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
Glossographer answered 23/2 at 10:33 Comment(2)
Fix your Spring Boot 3.2.x issue, rather than manually meddling with the transitive dependency. You will have to do it anyway sooner or later - you should not get stuck with SB 3.0.x.Stat
That is possible but right now I am 1 version behind the newest which is not so bad and if this is some bug related with lombok compatibility and new version of SB, then waiting for another release would be wiser then deal with it right now.Glossographer
P
2

I was facing same issue. And i had also make it 1.18.30. But still it was not working. In that i was making mistake in annotationProcessorPaths. In that i had also dependency of projectlombok but version given 1.18.28 and it was not working. So final change below working fine.

  • Spring boot 3.2.2

  • Java 21

  • projectlombok 1.18.30

  • <org.projectlombok.version>1.18.30</org.projectlombok.version>

     <annotationProcessorPaths>
                 <path>
                     <groupId>org.mapstruct</groupId>
                     <artifactId>mapstruct-processor</artifactId>
                     <version>${org.mapstruct.version}</version>
                 </path>
                 <path>
                     <groupId>org.projectlombok</groupId>
                     <artifactId>lombok</artifactId>
                     <version>${org.projectlombok.version}</version>
                 </path>
                 <path>
                     <groupId>org.projectlombok</groupId>
                     <artifactId>lombok-mapstruct-binding</artifactId>
                     <version>${lombok-mapstruct-binding.version}</version>
                 </path>
             </annotationProcessorPaths>
    
Phrixus answered 17/2 at 11:6 Comment(1)
Notice that ${org.projectlombok.version} is NOT the default spring boot lombok version property. Use ${lombok.version} if your idea is to overload the value from spring-boot-dependencies.Stinky
R
1

Note that if you still get the error after updating to 1.18.30 in IntelliJ even after you rerun the build, its because IntelliJ has some cache which is still picking up the previous lombok version. Try one of these in that case:

  1. Right click the pom.xml file and select Maven > Reimport or Maven > Reload (for newer versions of IntelliJ)
  2. Restart IntelliJ (noob, but the best solution usually)
Rattletrap answered 30/1 at 15:0 Comment(1)
True, however the question was IDE agnostic. So it should not be posted as an answer, but rather as a comment.Stat
M
-2

This work for me

Replace this:

...
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.XX</version>
  <scope>provided</scope>
</dependency>
...

With this:

...
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.30</version>
  <scope>provided</scope>
</dependency>
...
Musjid answered 31/12, 2023 at 15:35 Comment(1)
What new does your answer bring which have not been already said in the other answers?Stat
A
-2

Actually, even I've been getting the same error but for me, all I need to do was to change the Java JDK version and the Language level in the Project Structure (I had the following configuration in my project :-

  • Spring boot version 2.7.0
  • Lombok version is 1.18.24
  • Java 11

Project Structure

Allelomorph answered 17/2 at 16:21 Comment(3)
You didn't solve the problem, by doing this you just pretend the problem doesn't exist :) The purpose of upgrading to JDK 21 is usually that you want to get the Java 21 Java language features, not Java 11 features :)Stat
Buddy, my project was meant to run on Java 11 only, so why I'd upgrade it to JDK 21. The main concern was that I've been getting the same error that you were experiencing earlier.Allelomorph
@AMITPRAJAPATI i think u have configured the pom with wrong dependecies. You might have to use lower versions which is compactible with java 11. Above answer have nothing to do with problem we are facing with java 21 version. Also masking something might help to run in your system but when you containerise it might fail. Always do proper fix for the solution rather than fix just with IDE.Gilud
C
-3

I have faced this problem before, and that's because Lombok has compatibility issues with any Java JDK lower than 21 in any other version different from:

1.18.30

Just go into your pom file and change it to:

        <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version>
        <scope>provided</scope>
    </dependency>
Costive answered 4/2 at 15:40 Comment(2)
Welcome to SO @JCrick. The answer you posted here is a duplicate of the accepted answer.Tinge
Glad that you have copied an accepted answer above... But copy that to here itself.... thats not what SO is for mate.Gilud

© 2022 - 2024 — McMap. All rights reserved.