elastic/elasticsearch · error · UncheckedIOException

Can't copy extra jar dependency {} to {}

Error message

Can't copy extra jar dependency {} to {}

What it means

Thrown by copyExtraJars() when Files.copy of a validated jar into <distro>/lib fails with an IOException, wrapped as UncheckedIOException. The jar passed the .jar suffix check but the copy itself failed. Message includes source filename and destination path for diagnosis.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java:653

    private void copyExtraJars() {
        List<File> extraJarFiles = this.extraJarConfigurations.stream()
            .flatMap(fileCollection -> fileCollection.getFiles().stream())
            .toList();

        if (extraJarFiles.isEmpty() == false) {
            logToProcessStdout("Setting up " + this.extraJarConfigurations.size() + " additional jar dependencies");
        }
        extraJarFiles.forEach(from -> {
            if (from.getName().endsWith(".jar") == false) {
                throw new IllegalArgumentException("extra jar file " + from + " doesn't appear to be a JAR");
            }

            Path destination = getDistroDir().resolve("lib").resolve(from.getName());
            try {
                Files.copy(from.toPath(), destination, StandardCopyOption.REPLACE_EXISTING);
                LOGGER.info("Added extra jar {} to {}", from.getName(), destination);
            } catch (IOException e) {
                throw new UncheckedIOException("Can't copy extra jar dependency " + from.getName() + " to " + destination, e);
            }
        });
    }

    private void configureSecurity() {
        if (credentials.isEmpty() == false) {
            logToProcessStdout("Setting up " + credentials.size() + " users");

            credentials.forEach(
                paramMap -> runElasticsearchBinScript(
                    getVersion().onOrAfter("6.3.0") ? "elasticsearch-users" : "x-pack/users",
                    paramMap.entrySet().stream().flatMap(entry -> Stream.of(entry.getKey(), entry.getValue())).toArray(String[]::new)
                )
            );

            // If we added users, then also add the standard test roles
            rolesFile(getBuildPluginFile("/roles.yml"));
        }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Read the cause IOException for the exact FS error.
  2. rm -rf build/testclusters/<node> to force a clean distro dir on next start.
  3. Free disk / inodes; check permissions on build/testclusters.
  4. Shorten build path on Windows to avoid MAX_PATH in <distro>/lib/<long-jar-name>.
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm distro lib dir is writable
Path lib = node.getDistroDir().resolve("lib");
if (Files.exists(lib) && !Files.isWritable(lib)) {
    throw new IllegalStateException("<distro>/lib not writable: " + lib);
}

Try / catch

try {
    node.start();
} catch (UncheckedIOException e) {
    if (e.getMessage().startsWith("Can't copy extra jar dependency")) {
        throw new IllegalStateException("Jar copy FS failure: " + e.getCause(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Disk full, permission denied on <distro>/lib, antivirus locking the destination on Windows, or path-too-long. The distro lib dir may not exist if setupNodeDistribution partially failed, or a prior copy left a read-only file at the destination despite REPLACE_EXISTING.

Common situations: Windows CI long path / AV lock. Permission residue from a root-owned prior run. Stale distro dir. Disk pressure on the build agent.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/109e97df59ba9d37. Report an issue: GitHub.