{"record":{"id":"48a21edbb2c928dd","repo":"elastic/elasticsearch","slug":"native-image-classpath-is-empty","errorCode":null,"errorMessage":"Native-image classpath is empty","messagePattern":"Native-image classpath is empty","errorType":"exception","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java","lineNumber":162,"sourceCode":"            this.execOperations = execOperations;\n        }\n\n        @Override\n        public void execute() {\n            Parameters params = getParameters();\n            String imageTag = params.getImageTag().get();\n            String platform = params.getPlatform().get();\n            String mainClass = params.getMainClass().get();\n            File outputFile = params.getOutputFile().get().getAsFile();\n            File outputDir = outputFile.getParentFile();\n\n            if (outputDir.exists() == false && outputDir.mkdirs() == false) {\n                throw new GradleException(\"Failed to create output directory: \" + outputDir);\n            }\n\n            List<File> classpathFiles = params.getClasspath().getFiles().stream().filter(File::exists).collect(Collectors.toList());\n            if (classpathFiles.isEmpty()) {\n                throw new GradleException(\"Native-image classpath is empty\");\n            }\n\n            // Build classpath string for inside the container: /cp/0:/cp/1:...\n            List<String> cpPaths = new ArrayList<>();\n            for (int i = 0; i < classpathFiles.size(); i++) {\n                cpPaths.add(\"/cp/\" + i);\n            }\n            // Container is always Linux\n            String cpString = String.join(\":\", cpPaths);\n\n            List<String> args = new ArrayList<>();\n            args.add(\"run\");\n            args.add(\"--rm\");\n            for (int i = 0; i < classpathFiles.size(); i++) {\n                File f = classpathFiles.get(i);\n                String path = f.getAbsolutePath();\n                if (File.separatorChar == '\\\\') {\n                    path = path.replace(\"\\\\\", \"/\");","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java#L144-L180","documentation":"Thrown inside NativeImageBuildAction.execute() when the classpath file collection, after filtering with File::exists, contains zero entries. The classpath is passed to native-image inside a Docker container. If every JAR or directory on the classpath does not exist on the filesystem, the filtered list is empty and the build fails before launching Docker.","triggerScenarios":"params.getClasspath().getFiles() returns a set of File objects, but none of them exist on disk. This happens when the classpath is configured from a configuration whose dependencies have not been resolved/downloaded, when the task runs before its classpath-producing dependency, or when the classpath references stale or cleaned-up artifacts.","commonSituations":"The task depends on a JAR that was never built because its producing task was skipped or excluded. The Gradle build cache or a clean operation removed intermediate artifacts. The classpath configuration is misconfigured to reference output directories that don't exist yet (e.g., a source set's output before compilation).","solutions":["Ensure the task declares proper dependencies on the tasks that produce its classpath: nativeImageBuild.dependsOn(jar) or use the configuration's builtOutputs.","Check that the classpath configuration resolves to real artifacts: ./gradlew dependencies --configuration <configName>.","If classpath entries are output directories, ensure the corresponding compile task runs first by wiring dependsOn.","Run a clean full build to regenerate all artifacts: ./gradlew clean assemble."],"exampleFix":"// before\ntasks.named('nativeImageBuild') {\n    classpath = sourceSets.main.runtimeClasspath // may not be resolved yet\n}\n\n// after\ntasks.named('nativeImageBuild') {\n    classpath = sourceSets.main.runtimeClasspath\n    dependsOn(tasks.named('jar')) // ensure artifacts exist\n}","handlingStrategy":"validation","validationCode":"// Validate classpath before task execution\nList<File> existing = classpath.getFiles().stream().filter(File::exists).collect(Collectors.toList());\nif (existing.isEmpty()) {\n    throw new GradleException(\"Classpath is empty — ensure producing tasks have run: \" + classpath.getFiles());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always declare dependsOn for tasks producing the classpath artifacts.","Use configurations that resolve lazily (from source set runtimeClasspath) rather than hardcoded paths.","Run a clean full build if intermediate artifacts are missing."],"tags":["native-image","classpath","build-task","configuration"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}