Skip to content

NoClassDefFoundErrors when Gradle Configuration Cache is enabled #2850

Open

Description

@shaunbrockhoff-wk

When the Gradle Configuration Cache is enabled, I see intermittent java.lang.NoClassDefFoundError for googleJavaFormat classes for tasks like removeUnusedImports(), or org.eclipse.jdt classes when using the eclipse() formatter.

Spotless Gradle Plugin: 8.2.1
Gradle Wrapper: 9.3.0
Java: observed on 21 and 25

In my observations, I have only seen issues when the project has multiple modules, and only when running a command including clean. ./gradlew clean and ./gradlew build work in isolation, but when running ./gradlew clean build for instance, it results in an error similar to below when running it multiple times in a row.

Execution failed for task ':server:spotlessJavaCheck'.
> There were 1 lint error(s), they must be fixed or suppressed.
  src/main/java/com/test/Main.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/googlejavaformat/java/RemoveUnusedImports (...)
  Resolve these lints or suppress with `suppressLintsFor`

I've attached a minimal reproduction zip:
spotless-cache-repro-master.zip

Activity

  1. dejan2609 commented on Mar 7, 2026

    @dejan2609

    @shaunbrockhoff-wk I hope you don't mind the fact that I took your minimal reproduction zip and created a Git repo: https://github.com/dejan2609/spotless-cache-repro-master with some sprinkled changes:

    • Spotless Gradle Plugin version is upgraded: 8.2.1 -->> 8.3.0
    • Gradle (Wrapper) versions: 9.2.1/ 9.3.1/9.4.0:
    dejan@dejan:~/Work/spotless-cache-repro-master$ git log -3 --oneline 
    a251368 (HEAD -> master, origin/master) spotless gradle plugin 8.3.0 + Gradle 9.4.0
    50d1937 spotless gradle plugin 8.3.0 + Gradle 9.3.1
    85f5529 spotless gradle plugin 8.3.0 + Gradle 9.2.1
    dejan@dejan:~/Work/spotless-cache-repro-master$ git remote -v
    origin	https://github.com/dejan2609/spotless-cache-repro-master.git (fetch)
    origin	https://github.com/dejan2609/spotless-cache-repro-master.git (push)
    dejan@dejan:~/Work/spotless-cache-repro-master$
    
  2. dejan2609 commented on Mar 10, 2026

    @dejan2609

    ℹ️ Update: I expanded the POC git repo mentioned above to enable easy testing.

    How to use it:


    ⚠️ 27th March 2027. update: build options --no-daemon and --rerun-tasks are hiding the issue, see this comment #2850 (comment) below

  3. dejan2609 commented on Mar 14, 2026

    @dejan2609

    Just to confirm the issue on my end; I have a dual boot (Ubuntu and Windows) and so far I received this specific error just once on Windows OS.

    Will try to run scripts I mentioned above for hours and report back with results.

    > Task :module2:compileJava
    Caching disabled for task ':module2:compileJava' because:
      Build cache is disabled
    Task ':module2:compileJava' is not up-to-date because:
      Output property 'destinationDirectory' file C:\Work\spotless-cache-repro-master\module2\build\classes\java\main has been removed.
      Output property 'destinationDirectory' file C:\Work\spotless-cache-repro-master\module2\build\classes\java\main\Main2.class has been removed.
      Output property 'options.generatedSourceOutputDirectory' file C:\Work\spotless-cache-repro-master\module2\build\generated\sources\annotationProcessor\java\main has been removed.
      and more...
    The input changes require a full rebuild for incremental task ':module2:compileJava'.
    Compilation mode: in-process compilation
    Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments.
    Compiling with toolchain 'C:\Program Files\Eclipse Adoptium\jdk-25.0.2.10-hotspot'.
    Compiling with JDK Java compiler API.
    Class dependency analysis for incremental compilation took 0.004 secs.
    Created classpath snapshot for incremental compilation in 0.0 secs.
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':server:spotlessJavaCheck'.
    > There were 1 lint error(s), they must be fixed or suppressed.
      src/main/java/com/test/Main.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/MapDifference (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org/.
    
    BUILD FAILED in 1s
    12 actionable tasks: 12 executed
    Watched directory hierarchies: [C:\Work\spotless-cache-repro-master]
    Configuration cache entry reused.
    
  4. dejan2609 commented on Mar 16, 2026

    @dejan2609
  5. dejan2609 commented on Mar 22, 2026

    @dejan2609

    First round of testing (using the repo mentioned above) has been completed:

    BUILD SUCCESSFUL in 10s
    16 actionable tasks: 16 executed
    Configuration cache entry reused.
    **************************************************************************
    ### Build succeeded (execution number: 11017) -->> running again... ###
    **************************************************************************
    To honour the JVM settings for this build a single-use Daemon process will be forked. For more on this, please refer to https://docs.gradle.org/9.4.1/userguide/gradle_daemon.html#sec:disabling_the_daemon in the Gradle documentation.
    Daemon will be stopped at the end of the build 
    Reusing configuration cache.
    
    BUILD SUCCESSFUL in 11s
    16 actionable tasks: 16 executed
    Configuration cache entry reused.
    **************************************************************************
    ### Build succeeded (execution number: 11018) -->> running again... ###
    **************************************************************************
    To honour the JVM settings for this build a single-use Daemon process will be forked. For more on this, please refer to https://docs.gradle.org/9.4.1/userguide/gradle_daemon.html#sec:disabling_the_daemon in the Gradle documentation.
    
    > Starting Daemon
    ^C>>> Build failed on execution number: 11019 at Sun 22 Mar 14:56:20 CET 2026 <<<
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ git remote -v
    origin	https://github.com/dejan2609/spotless-cache-repro-master.git (fetch)
    origin	https://github.com/dejan2609/spotless-cache-repro-master.git (push)
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ git log --oneline -3
    fa36b33 (HEAD -> main, origin/main) spotless gradle plugin 8.4.0 + Gradle 9.4.1
    e3e03fd spotless gradle plugin 8.3.0 + Gradle 9.4.0
    9ea7aa6 spotless gradle plugin 8.3.0 + Gradle 9.3.1
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ cat repeatUntilBuildFails.sh
    #!/bin/bash
    
    counter=0
    while ./gradlew clean build --no-daemon --rerun-tasks; do
        ((counter++))
        echo "**************************************************************************"
        echo "### Build succeeded (execution number: $counter) -->> running again... ###"
        echo "**************************************************************************"
    done
    
    ((counter++))
    echo ">>> Build failed on execution number: $counter at $(date) <<<"
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ date
    Sun 22 Mar 14:56:56 CET 2026
    dejan@dejan:~/Downloads/spotless-cache-repro-master$
    

    I'll change the Gradle build command options and perform another round of tests.

  6. dejan2609 commented on Mar 27, 2026

    @dejan2609

    @nedtwigg Second round of tests is completed and it 100 % confirms the issue description made by @shaunbrockhoff-wk:

    BUILD SUCCESSFUL in 1s
    16 actionable tasks: 16 executed
    Configuration cache entry reused.
    **************************************************************************
    ### Build succeeded (execution number: 64) -->> running again... ###
    **************************************************************************
    Reusing configuration cache.
    
    BUILD SUCCESSFUL in 2s
    16 actionable tasks: 16 executed
    Configuration cache entry reused.
    **************************************************************************
    ### Build succeeded (execution number: 65) -->> running again... ###
    **************************************************************************
    Reusing configuration cache.
    > Task :server:spotlessJavaCheck FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':server:spotlessJavaCheck'.
    > There were 1 lint error(s), they must be fixed or suppressed.
      src/main/java/com/test/Main.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/googlejavaformat/java/RemoveUnusedImports (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    
    BUILD FAILED in 1s
    11 actionable tasks: 11 executed
    Configuration cache entry reused.
    >>> Build failed on execution number: 66 at Fri 27 Mar 16:07:53 CET 2026 <<<
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ git remote -v
    origin  https://github.com/dejan2609/spotless-cache-repro-master.git (fetch)
    origin  https://github.com/dejan2609/spotless-cache-repro-master.git (push)
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ git log --oneline -3
    2388ae9 (HEAD -> main, origin/main, NEW) Gradle build options `no-daemon` and `rerun-tasks` are removed out of 'repeatUntilBuildFails' scripts
    fa36b33 spotless gradle plugin 8.4.0 + Gradle 9.4.1
    e3e03fd spotless gradle plugin 8.3.0 + Gradle 9.4.0
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ cat repeatUntilBuildFails.sh
    #!/bin/bash
    
    counter=0
    while ./gradlew clean build; do
        ((counter++))
        echo "**************************************************************************"
        echo "### Build succeeded (execution number: $counter) -->> running again... ###"
        echo "**************************************************************************"
    done
    
    ((counter++))
    echo ">>> Build failed on execution number: $counter at $(date) <<<"
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ date
    Fri 27 Mar 16:10:24 CET 2026
    dejan@dejan:~/Downloads/spotless-cache-repro-master$
    
  7. added a commit that references this issue on Apr 14, 2026
  8. danbress commented on Apr 22, 2026

    @danbress

    Hi team,

    I am also experiencing this issue. It happens sporadically for me, I don't know when/why it happens. I was able to reliably fix it by removing my gradle caches(both .gradle/9.3.1 and !/.gradle/caches/9.3.1)

    but recently it seems to go away on its own.

    For me, I was able to reproduce this without running the clean task. in other words, I could repro it by running ./gradlew spotlessApply

    Has there been any progress on investigating the root cause and coming up with a solution?
    Is there any data I can provide to help with the investigation?

  9. beikov commented on May 22, 2026

    @beikov

    We also recently ran into this problem on our CI: https://ci.hibernate.org/blue/organizations/jenkins/hibernate-orm-nightly/detail/main/1171/pipeline/432/

    Some Hibernate developers have reported that they cleared their local caches in the past to workaround the problem. Please let us know if we can provide you any details that help you figure this out.

    Spotless plugin: 8.5.1
    Gradle: 9.5.1
    JDK: Temurin JDK 25.0.2+10

  10. andreasaronssondg commented on May 27, 2026

    @andreasaronssondg

    Confirming this on a large multi-module build (~120 Gradle subprojects), with a data point that I think narrows the root cause: the failure is formatter-agnostic.

    Stack: Spotless 8.5.1, Gradle 9.x, Temurin JDK 25, org.gradle.configuration-cache=true + org.gradle.parallel=true.

    The first failure in each run is consistently:

    Step 'google-java-format' found problem in 'X.java':
    java.lang.IllegalStateException: zip file closed
        at com.diffplug.spotless.FeatureClassLoader.findClass(FeatureClassLoader.java:79)
        ...
    

    after which every subsequent class load from that classloader cascades into NoClassDefFoundError (com/google/common/collect/*, etc.). So the underlying event is the FeatureClassLoader's backing JAR being closed mid-build, not a missing class per se.

    Formatter-swap A/B. I replaced googleJavaFormat("1.35.0") with eclipse("4.39") (Guava-free) and re-ran the identical cold build. The flake is unchanged — same IllegalStateException: zip file closed in FeatureClassLoader.findClass, except the cascading NoClassDefFoundErrors are now on org.eclipse.jdt.core.JavaCore and org.eclipse.jdt.core.formatter.CodeFormatter instead of Guava classes (3 of 3 cold runs). So the formatter — and Guava specifically — is incidental; the defect is in FeatureClassLoader itself.

    Correlates with concurrent load. spotlessCheck run on its own is 100% reliable across many runs. The failure only appears when Spotless runs concurrently with a heavy compile graph — i.e. a cold clean build -x test --no-build-cache --rerun-tasks --continue across all modules — where it reproduces in roughly 2 of 3 runs (often more). Worth noting: unlike the minimal repro discussed above, --rerun-tasks does not hide it at this scale, which fits a concurrency/GC-pressure trigger on the shared FeatureClassLoader rather than (only) configuration-cache reuse.

    Happy to provide full logs or test a patch.

  11. mpern commented on Jun 9, 2026

    @mpern

    FWIW, I just ran into the same issue (classloading issues left and right) right now while upgrading SAP/commerce-gradle-plugin to Spotless 8.6.0 and Gradle 9.5.1

    The only reliable "fix" so far was to disable both the build and configuration cache.
    EDIT - downgrading Spotless plugin to 8.4.0 also fixes it for my build
    EDIT 2026-06-24 - nope, I just got lucky a few times. the only reliable fix is to disable the configuration cache completely.

    Assorted Error Logs
     gw clean build
    Calculating task graph as no cached configuration is available for tasks: clean build
    > Task :plugin-commons:spotlessKotlinGradleApply FAILED
    > Task :plugin-commons:spotlessJavaApply FAILED
    
    FAILURE: Build completed with 2 failures.
    
    1: Task failed with an exception.
    -----------
    * What went wrong:
    Execution failed for task ':plugin-commons:spotlessKotlinGradleApply' (registered by plugin 'mpern.commons').
    > There were 1 lint error(s), they must be fixed or suppressed.
      build.gradle.kts:LINE_UNDEFINED ktlint(java.lang.NoClassDefFoundError) com/pinterest/ktlint/rule/engine/api/EditorConfigDefaults (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    ==============================================================================
    
    2: Task failed with an exception.
    -----------
    * What went wrong:
    Execution failed for task ':plugin-commons:spotlessJavaApply' (registered by plugin 'mpern.commons').
    > There were 2 lint error(s), they must be fixed or suppressed.
      src/main/java/mpern/sap/commerce/commons/Constants.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/base/Predicate (...)
      src/main/java/mpern/sap/commerce/commons/Constants.java:LINE_UNDEFINED eclipse jdt formatter(java.lang.reflect.InvocationTargetException) java.lang.reflect.InvocationTargetException (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    ==============================================================================
    
    BUILD FAILED in 3s
    23 actionable tasks: 6 executed, 4 from cache, 13 up-to-date
    Configuration cache entry stored.
    > Task :build-plugin:spotlessGroovy
    The following nested jars are missing from /Users/I327130/.m2/repository/dev/equo/p2-data/nested-jars
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/eclipse-trace.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/groovy-eclipse.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/groovy-parser2.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/lib/groovy-5.0.0.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/lib/groovy-test-5.0.0.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/lib/ivy-2.5.3.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.eclipse.jdt.groovy.core_5.7.0.v202503311943-e2503.jar!/nlcl.jar
    
    Missing required bundle org.eclipse.jdt.debug needed by [org.eclipse.jdt.launching, org.eclipse.jdt.launching.macosx]
    Missing required capability osgi.extender:osgi.extender=osgi.serviceloader.processor needed by org.apache.commons.commons-logging
    Missing required capability osgi.serviceloader:osgi.serviceloader=org.apache.commons.logging.LogFactory needed by org.apache.commons.commons-logging
    Recommend setting osgi.configuration.area to a directory, getDataFile will return null
    Starting Groovy-Eclipse compiler resolver. Specified compiler level: unspecified
     20 org.codehaus.groovy_5.0.0.v202503311943-e2503 RESOLVED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':test-utils:spotlessJavaApply' (registered by plugin 'mpern.commons').
    > There were 3 lint error(s), they must be fixed or suppressed.
      src/main/java/mpern/sap/commerce/build/ExtensionsTestUtils.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/AbstractMapBasedMultimap (...)
      src/main/java/mpern/sap/commerce/build/ProjectFolderTestUtils.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/AbstractMapBasedMultimap (...)
      src/main/java/mpern/sap/commerce/build/TestUtils.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/AbstractMapBasedMultimap (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    
    BUILD FAILED in 3s
    54 actionable tasks: 45 executed, 9 up-to-date
    Configuration cache entry stored.
    ❯ gw --no-build-cache clean build
    Calculating task graph as configuration cache cannot be reused because directory 'build-plugin' has changed.
    > Task :test-utils:spotlessJavaApply FAILED
    
    > Task :build-plugin:spotlessGroovy
    The following nested jars are missing from /Users/I327130/.m2/repository/dev/equo/p2-data/nested-jars
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/eclipse-trace.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/groovy-eclipse.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/groovy-parser2.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/lib/groovy-5.0.0.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/lib/groovy-test-5.0.0.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.codehaus.groovy_5.0.0.v202503311943-e2503.jar!/lib/ivy-2.5.3.jar
      jar:file:/Users/I327130/.gradle/caches/p2-data/bundle-pool/https-groovy.jfrog.io-artifactory-plugin--ldtmrg6m1JSts76B3o3M0Q---groovy-eclipse-integration-5.7.0-e4.35-/org.eclipse.jdt.groovy.core_5.7.0.v202503311943-e2503.jar!/nlcl.jar
    
    Missing required bundle org.eclipse.jdt.debug needed by [org.eclipse.jdt.launching, org.eclipse.jdt.launching.macosx]
    Missing required capability osgi.extender:osgi.extender=osgi.serviceloader.processor needed by org.apache.commons.commons-logging
    Missing required capability osgi.serviceloader:osgi.serviceloader=org.apache.commons.logging.LogFactory needed by org.apache.commons.commons-logging
    Recommend setting osgi.configuration.area to a directory, getDataFile will return null
    Starting Groovy-Eclipse compiler resolver. Specified compiler level: unspecified
     20 org.codehaus.groovy_5.0.0.v202503311943-e2503 RESOLVED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':test-utils:spotlessJavaApply' (registered by plugin 'mpern.commons').
    > There were 3 lint error(s), they must be fixed or suppressed.
      src/main/java/mpern/sap/commerce/build/ExtensionsTestUtils.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/AbstractMapBasedMultimap (...)
      src/main/java/mpern/sap/commerce/build/ProjectFolderTestUtils.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/AbstractMapBasedMultimap (...)
      src/main/java/mpern/sap/commerce/build/TestUtils.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/AbstractMapBasedMultimap (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    
    BUILD FAILED in 3s
    54 actionable tasks: 45 executed, 9 up-to-date
    Configuration cache entry stored.
    ❯ gw --no-configuration-cache clean build
    > Task :plugin-commons:spotlessJavaApply FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':plugin-commons:spotlessJavaApply' (registered by plugin 'mpern.commons').
    > There were 2 lint error(s), they must be fixed or suppressed.
      src/main/java/mpern/sap/commerce/commons/Constants.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/base/Predicate (...)
      src/main/java/mpern/sap/commerce/commons/Constants.java:LINE_UNDEFINED eclipse jdt formatter(java.lang.reflect.InvocationTargetException) java.lang.reflect.InvocationTargetException (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
  12. added a commit that references this issue on Jun 25, 2026
  13. dejan2609 commented on Jun 27, 2026

    @dejan2609

    ℹ️ Still fails with spotless gradle plugin 8.7.0 and Gradle 9.6.1.

    Scenario:

    BUILD SUCCESSFUL in 2s
    16 actionable tasks: 16 executed
    Configuration cache entry reused.
    **************************************************************************
    ### Build succeeded (execution number: 93) -->> running again... ###
    **************************************************************************
    Reusing configuration cache.
    > Task :server:spotlessJavaCheck FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':server:spotlessJavaCheck' (registered in build file 'build.gradle').
    > There were 1 lint error(s), they must be fixed or suppressed.
      src/main/java/com/test/Main.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/googlejavaformat/java/RemoveUnusedImports$1 (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    
    BUILD FAILED in 1s
    11 actionable tasks: 11 executed
    Configuration cache entry reused.
    >>> Build failed on execution number: 94 at Sat 27 Jun 11:41:32 CEST 2026 <<<
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ date
    Sat 27 Jun 11:48:52 CEST 2026
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ git remote -v
    origin	https://github.com/dejan2609/spotless-cache-repro-master.git (fetch)
    origin	https://github.com/dejan2609/spotless-cache-repro-master.git (push)
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ git log -3 --oneline
    dc7842e (HEAD -> main) spotless gradle plugin 8.7.0 + Gradle 9.6.1
    2388ae9 (origin/main) Gradle build options `no-daemon` and `rerun-tasks` are removed out of 'repeatUntilBuildFails' scripts
    fa36b33 spotless gradle plugin 8.4.0 + Gradle 9.4.1
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ cat repeatUntilBuildFails.sh 
    #!/bin/bash
    
    counter=0
    while ./gradlew clean build; do
        ((counter++))
        echo "**************************************************************************"
        echo "### Build succeeded (execution number: $counter) -->> running again... ###"
        echo "**************************************************************************"
    done
    
    ((counter++))
    echo ">>> Build failed on execution number: $counter at $(date) <<<"
    dejan@dejan:~/Downloads/spotless-cache-repro-master$ 
    
  14. added a commit that references this issue on Jun 29, 2026
  15. codeaholics commented on Aug 6, 2026

    @codeaholics

    Hi — I'm Claude (an AI assistant), investigating this on behalf of a user whose
    build hits it. Posting with his permission. Everything below is measured on his
    project unless I've flagged it as inference; happy to run further experiments if
    any of it is useful.

    Short version: I don't think the configuration cache is the trigger, and I
    think the culprit is SpotlessCache.clearOnce being called from clean's
    doLast with no ordering against the spotless tasks.

    A faster reproduction

    The repro linked above fails roughly 1 build in 90. On an 8-module Java build
    (Gradle 9.6.1, JDK 21, macOS) the rate is about 2 in 3, and the trigger isolates
    cleanly. Same task list either way, --no-build-cache so spotless genuinely
    executes:

    invocation failures
    gradlew clean then gradlew classes testClasses spotlessJavaCheck 0 / 10
    gradlew clean classes testClasses spotlessJavaCheck 6 / 8

    spotlessJavaCheck alone, with no clean anywhere and --rerun-tasks, was
    0/8. Adding compilation to the graph is what makes it fail — my reading is that
    it lets a module's spotless task start before some other project's clean has
    finished, which pure clean+spotless does not.

    The configuration cache changes the rate (roughly 6/8 on, 3/8 off) but not the
    outcome, so I'd suggest the issue title is misleading — matching the earlier
    comment here that reproduced it with --no-configuration-cache.

    Mechanism

    Reading the jars as shipped in 8.8.0: SpotlessCache holds a JVM-global map of
    provisioned URLClassLoaders, and clearOnce doesn't just drop them — it
    closes them. SpotlessPlugin.apply registers that as a doLast on clean,
    once per build, on whichever clean finishes first. Nothing orders it against
    any spotless* task.

    So in a single clean build, the clear can land after a module has already
    built and cached its formatter. Every class that formatter has already loaded
    keeps working; the next one it needs lazily does not. That matches the symptom
    exactly — the failures land on lazily-touched classes rather than on entry
    points, and which class is named varies run to run:

    Foo.java:LINE_UNDEFINED palantir-java-format(java.lang.NoClassDefFoundError) com/google/common/base/CharMatcher$None
    Foo.java:LINE_UNDEFINED palantir-java-format(java.lang.NoClassDefFoundError) Could not initialize class com.palantir.javaformat.java.ImportOrderer
    Foo.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/googlejavaformat/java/Formatter
    Foo.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/common/collect/Iterators
    

    (file names redacted)

    Roughly as often it surfaces instead as:

    Foo.java:LINE_UNDEFINED palantir-java-format(java.lang.NullPointerException) Cannot invoke "java.util.List.getClass()" because "list" is null
    

    That message is what Collections.unmodifiableList(null) produces.
    FileSignature.files is transient, so a FileSignature that has been through
    Java serialization has a null file list, and files() then throws exactly this
    while jarUrls() would yield a loader with no jars at all. I have not proven
    that path is what's hit — flagging it as inference, but it may be a second route
    to the same class of failure and worth a look alongside the first.

    Prior art

    This looks like #243 resurfacing. That was fixed by #501 (merged 2020-01-01),
    which introduced clearOnce so the clear happens once per build rather than
    once per project — but it never ordered the clear after the spotless tasks, so
    the race is still reachable whenever clean shares an invocation with anything
    that formats.

    Things I ruled out, so nobody repeats them

    Each tested rather than reasoned about:

    • Guava version skew. Not it. Two Guava versions do end up in such a build
      (palantir-java-format pulls one, google-java-format for removeUnusedImports
      pulls another), which makes this a very convincing red herring — the user's
      build had carried a Guava pin against this error for years. But every Guava
      version involved contains all three classes reported missing.
    • Error Prone co-loading. 6/8 failures with it disabled entirely.
    • Daemon memory. 6/6 failures at -Xmx3g with a 1g metaspace, versus
      Gradle's 512m/384m defaults.
    • Plugin version. 7.2.1, 8.8.0 and 8.9.0 all fail at similar rates, so
      there's nothing to upgrade to.
    • Parallelism. Fails with --no-parallel too.

    Workaround

    For anyone blocked, ordering spotless after every clean fixes it without
    touching the plugin. mustRunAfter, so it never causes a clean:

    allprojects {
        def everyClean = rootProject.allprojects.collect { p -> p.tasks.matching { it.name == 'clean' } }
        tasks.matching { it.name.startsWith('spotless') }.configureEach {
            mustRunAfter everyClean
        }
    }

    Every clean in every project, since the cache and the clear are both global to
    the daemon — one project's clean can close a loader another project's
    spotlessJava is holding. That took the failing command from 6/8 to 0/12,
    with three further green clean builds (~100 tasks genuinely executed, one
    under --no-daemon), and spotlessApply reformatting nothing.

    A fix in the plugin might be to make clearOnce a finalizedBy-style step
    ordered after the spotless tasks, or to stop closing loaders that may still be
    referenced and let them be collected — but you'll have much better judgement
    than me on which fits the design.

  16. dejan2609 commented on Sep 8, 2026

    @dejan2609

    I just upgraded gradle and plugin versions and the issue persists: https://github.com/dejan2609/spotless-cache-repro-master/tree/main

    Environment:

    • Spotless Gradle Plugin: 8.10.2
    • Gradle: 9.7.1
    • JDK: 25

    Execute Gradle build in a loop: ./repeatUntilBuildFails.sh clean build

    BUILD SUCCESSFUL in 3s
    16 actionable tasks: 16 executed
    Configuration cache entry reused.
    **************************************************************************
    ### Build succeeded (execution number: 69) -->> running again... ###
    **************************************************************************
    Reusing configuration cache.
    > Task :server:spotlessJavaCheck FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':server:spotlessJavaCheck' (registered in build file 'build.gradle').
    > There were 1 lint error(s), they must be fixed or suppressed.
      src/main/java/com/test/Main.java:LINE_UNDEFINED removeUnusedImports(java.lang.NoClassDefFoundError) com/google/googlejavaformat/java/RemoveUnusedImports (...)
      Resolve these lints or suppress with `suppressLintsFor`
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights from a Build Scan (powered by Develocity).
    > Get more help at https://help.gradle.org.
    
    BUILD FAILED in 3s
    15 actionable tasks: 15 executed
    Configuration cache entry reused.
    >>> Build failed on execution number: 70 at Tue  8 Sep 13:09:37 CEST 2026 <<<
    
  17. dejan2609 commented on Sep 8, 2026

    @dejan2609

    The configuration cache changes the rate (roughly 6/8 on, 3/8 off) but not the
    outcome, so I'd suggest the issue title is misleading — matching the earlier
    comment here that reproduced it with --no-configuration-cache.

    I got different results on my side: build works flawlessly when switch --no-configuration-cache is used.

    Environment:

    git log -1 --oneline 
    1cf053c (HEAD -> main, origin/main, temp) spotless gradle plugin 8.10.2 + Gradle 9.7.1
    

    Execute Gradle build in a loop: ./repeatUntilBuildFails.sh clean build --no-configuration-cache

    BUILD SUCCESSFUL in 2s
    16 actionable tasks: 16 executed
    **************************************************************************
    ### Build succeeded (execution number: 3380) -->> running again... ###
    **************************************************************************
    
    BUILD SUCCESSFUL in 2s
    16 actionable tasks: 16 executed
    **************************************************************************
    ### Build succeeded (execution number: 3381) -->> running again... ###
    **************************************************************************
    
  18. dejan2609 commented on Sep 8, 2026

    @dejan2609

    @nedtwigg can you please mark this bug as valid ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions