{"record":{"id":"109e97df59ba9d37","repo":"elastic/elasticsearch","slug":"can-t-copy-extra-jar-dependency-to","errorCode":null,"errorMessage":"Can't copy extra jar dependency {} to {}","messagePattern":"Can't copy extra jar dependency (.+?) to (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java","lineNumber":653,"sourceCode":"    private void copyExtraJars() {\n        List<File> extraJarFiles = this.extraJarConfigurations.stream()\n            .flatMap(fileCollection -> fileCollection.getFiles().stream())\n            .toList();\n\n        if (extraJarFiles.isEmpty() == false) {\n            logToProcessStdout(\"Setting up \" + this.extraJarConfigurations.size() + \" additional jar dependencies\");\n        }\n        extraJarFiles.forEach(from -> {\n            if (from.getName().endsWith(\".jar\") == false) {\n                throw new IllegalArgumentException(\"extra jar file \" + from + \" doesn't appear to be a JAR\");\n            }\n\n            Path destination = getDistroDir().resolve(\"lib\").resolve(from.getName());\n            try {\n                Files.copy(from.toPath(), destination, StandardCopyOption.REPLACE_EXISTING);\n                LOGGER.info(\"Added extra jar {} to {}\", from.getName(), destination);\n            } catch (IOException e) {\n                throw new UncheckedIOException(\"Can't copy extra jar dependency \" + from.getName() + \" to \" + destination, e);\n            }\n        });\n    }\n\n    private void configureSecurity() {\n        if (credentials.isEmpty() == false) {\n            logToProcessStdout(\"Setting up \" + credentials.size() + \" users\");\n\n            credentials.forEach(\n                paramMap -> runElasticsearchBinScript(\n                    getVersion().onOrAfter(\"6.3.0\") ? \"elasticsearch-users\" : \"x-pack/users\",\n                    paramMap.entrySet().stream().flatMap(entry -> Stream.of(entry.getKey(), entry.getValue())).toArray(String[]::new)\n                )\n            );\n\n            // If we added users, then also add the standard test roles\n            rolesFile(getBuildPluginFile(\"/roles.yml\"));\n        }","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java#L635-L671","documentation":"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.","triggerScenarios":"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.","commonSituations":"Windows CI long path / AV lock. Permission residue from a root-owned prior run. Stale distro dir. Disk pressure on the build agent.","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>."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Confirm distro lib dir is writable\nPath lib = node.getDistroDir().resolve(\"lib\");\nif (Files.exists(lib) && !Files.isWritable(lib)) {\n    throw new IllegalStateException(\"<distro>/lib not writable: \" + lib);\n}","typeGuard":null,"tryCatchPattern":"try {\n    node.start();\n} catch (UncheckedIOException e) {\n    if (e.getMessage().startsWith(\"Can't copy extra jar dependency\")) {\n        throw new IllegalStateException(\"Jar copy FS failure: \" + e.getCause(), e);\n    }\n    throw e;\n}","preventionTips":["Keep build/testclusters owned by the Gradle user.","Free disk before runs; monitor CI agent pressure.","Shorten paths on Windows."],"tags":["testclusters","classpath","io","filesystem"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}