Skip to content

Fix failing for non-existent class directories#1976

Merged
Goooler merged 4 commits intomainfrom
copilot/fix-shadowjar-cannot-expand-zip
Mar 14, 2026
Merged

Fix failing for non-existent class directories#1976
Goooler merged 4 commits intomainfrom
copilot/fix-shadowjar-cannot-expand-zip

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 14, 2026

When a source set has no Java sources (e.g., a custom api source set with Kotlin-only files), Gradle still adds build/classes/java/<sourceSet> to runtimeClasspath via sourceSet.output, even though the directory is never created. shadowJar then fails trying to unzip a path that doesn't exist.

Changes

  • ShadowJar.copy(): Added !file.exists() as the first branch in the when block, logging at debug level and skipping non-existent entries. Previously, file.isDirectory returned false for non-existent paths, causing them to fall through to archiveOperations.zipTree(file).
  • JavaPluginsTest: Added regression test skipNonExistentDependencyDirectory that adds a non-existent directory path to implementation dependencies and asserts shadowJar succeeds.

  • CHANGELOG's "Unreleased" section has been updated, if applicable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -Xmx4g -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant (dns block)
  • scans-in.gradle.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED -Xmx4g -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>shadowJar fails with "Cannot expand ZIP" when dependency includes non-existent class directory</issue_title>
<issue_description>### Expected and Results

When a project dependency includes a class output directory that does not exist (e.g., build/classes/java/api from a custom source set with no Java sources), shadowJar should gracefully skip it or treat it as an empty directory, rather than failing.

Actual behavior
shadowJar fails with:
Cannot expand ZIP '/path/to/project/build/classes/java/api' as it does not exist.

Related environment and versions

No response

Reproduction steps

  1. Create a multi-module Gradle project with a custom api source set:
  // root build.gradle.kts
  subprojects {
      sourceSets {
          val api by creating
          val main by getting {
              compileClasspath += api.output
              runtimeClasspath += api.output
          }
      }
  }
  1. In one of the submodules, apply the Shadow plugin and have Kotlin-only sources in the api source set (no Java files under src/api/java/).
  2. Run ./gradlew :module:shadowJar.
  3. The task fails because build/classes/java/api is included in runtimeClasspath via api.output, but the directory was never created since there are no Java sources to compile in that source set.

Anything else?

No response</issue_description>

Comments on the Issue (you are @copilot in this section)

@Goooler Any producer?

📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

Fixes #1975. When a project dependency includes a class output directory
that does not exist (e.g., build/classes/java/api from a custom source
set with no Java sources), shadowJar now gracefully skips it instead of
failing with "Cannot expand ZIP ... as it does not exist."

Also adds a functional test to verify the fix.

Co-authored-by: Goooler <10363352+Goooler@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix shadowJar failing on non-existent class directory Fix shadowJar failing with "Cannot expand ZIP" for non-existent class directories Mar 14, 2026
Copilot AI requested a review from Goooler March 14, 2026 15:33
@Goooler Goooler changed the title Fix shadowJar failing with "Cannot expand ZIP" for non-existent class directories Fix failing for non-existent class directories Mar 14, 2026
@Goooler Goooler marked this pull request as ready for review March 14, 2026 15:45
@Goooler Goooler enabled auto-merge (squash) March 14, 2026 15:48
@Goooler Goooler merged commit 85ba389 into main Mar 14, 2026
8 checks passed
@Goooler Goooler deleted the copilot/fix-shadowjar-cannot-expand-zip branch March 14, 2026 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

shadowJar fails with "Cannot expand ZIP" when dependency includes non-existent class directory

2 participants