github/copilot-sdk · error · IllegalStateException

Classpath resource is empty:

Error message

Classpath resource is empty: 

What it means

copyResourceToTemp copies a classpath resource to a temp file and counts bytes written; a zero-byte result means the resource opened successfully but contained no data. The loader throws IllegalStateException because an empty native binary/asset is never valid — publishing it would cache a broken executable. This indicates the bundled artifact resource is empty or the stream was truncated.

Solutions

  1. Verify the resource inside the jar is non-empty (unzip -l / jar tf and extract to compare sizes); replace the artifact if empty.
  2. Disable Maven resource filtering for binary/native resources (<filtering>false</filtering> on the native directory).
  3. Re-download/rebuild the artifact and confirm checksums match the official release.
  4. Clear the local cache dir so partial/truncated prior extractions aren't reused.

Example fix

// before (pom.xml)
<resource><directory>src/main/resources</directory><filtering>true</filtering></resource>
// after
<resource><directory>src/main/resources</directory><filtering>false</filtering><excludes><exclude>native/**</exclude></excludes></resource>
Defensive patterns

Strategy: validation

Validate before calling

// Java: verify classpath resources are non-empty before extraction
String resourcePath = "native/linux-x64/runtime.node";
try (InputStream in = loader.getResourceAsStream(resourcePath)) {
    if (in == null || in.read() == -1) throw new IllegalStateException("Empty/missing classpath resource: " + resourcePath);
}

Try / catch

try { loader.loadRuntime(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Classpath resource is empty")) { // artifact jar is corrupt: rebuild/re-download and verify checksum } else throw e; }

Prevention

When it happens

Trigger: resource.openStream() yields 0 bytes for 'native/<classifier>/<file>' or the CLI resource during any extraction path (resolveRuntimeWrapper, extractRuntimeToCache, extractRuntimeAssetsToCache, extractCliToCache).

Common situations: A 0-byte file committed into the artifact jar; a broken release build that packaged empty natives; download corruption when the jar was fetched; a stub/placeholder resource left by misconfigured resource filtering (maven filtering corrupting binaries).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/b5457e926292a59f. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java:585

        if (isWindows()) {
            return;
        }
        final boolean executableSet;
        try {
            executableSet = path.toFile().setExecutable(true, false);
        } catch (SecurityException ex) {
            throw new IOException("Failed to make Copilot CLI executable: " + path, ex);
        }
        if (!executableSet || !Files.isExecutable(path)) {
            throw new IOException("Failed to make Copilot CLI executable: " + path);
        }
    }

    private static void copyResourceToTemp(URL resource, String resourcePath, Path temp) throws IOException {
        try (InputStream in = resource.openStream()) {
            long bytesWritten = Files.copy(in, temp, StandardCopyOption.REPLACE_EXISTING);
            if (bytesWritten == 0) {
                throw new IllegalStateException("Classpath resource is empty: " + resourcePath);
            }
        }
        // Flush OS buffers to durable storage before the atomic rename.
        try (FileChannel channel = FileChannel.open(temp, StandardOpenOption.WRITE)) {
            channel.force(true);
        }
    }

    /**
     * Finds the Copilot CLI executable on the {@code PATH}.
     *
     * @return the absolute CLI path, or {@code null} if none was found
     */
    public static String findRuntimeOnPath() {
        String pathValue = System.getenv("PATH");
        if (pathValue == null || pathValue.isBlank()) {
            return null;
        }

View on GitHub (pinned to cd8cf15dc3)