elastic/elasticsearch · error · UncheckedIOException
Can't copy extra jar dependency
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.
Solutions
- Read the cause IOException for the exact FS error.
- rm -rf build/testclusters/<node> to force a clean distro dir on next start.
- Free disk / inodes; check permissions on build/testclusters.
- 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
- Keep build/testclusters owned by the Gradle user.
- Free disk before runs; monitor CI agent pressure.
- Shorten paths on Windows.
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
- Can't append roles file
- Can't create extra config file for
- Failed to create working directory for
- Failed to write unicast_hosts for
- Can not start , is not a directory
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/109e97df59ba9d37.
Report an issue: GitHub.
Appendix: 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)