{"record":{"id":"9c40d2d45ac302be","repo":"elastic/elasticsearch","slug":"failed-to-create-output-directory-outputdir","errorCode":null,"errorMessage":"Failed to create output directory: {outputDir}","messagePattern":"Failed to create output directory: (.+?)","errorType":"exception","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java","lineNumber":157,"sourceCode":"\n        private final ExecOperations execOperations;\n\n        @Inject\n        public NativeImageBuildAction(ExecOperations execOperations) {\n            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\");","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/NativeImageBuildTask.java#L139-L175","documentation":"Thrown inside NativeImageBuildAction.execute() (a Gradle WorkAction) when the output directory for the native-image binary cannot be created. The code checks if the parent directory of the configured output file exists; if not, it calls mkdirs(). If mkdirs() returns false and the directory still does not exist, it throws GradleException. This runs inside a Gradle worker with no isolation, so filesystem errors surface directly.","triggerScenarios":"The configured OutputFile's parent directory does not exist, File.mkdirs() returns false. This happens when: a parent path component is a regular file (not a directory), the path is on a read-only filesystem, permissions prevent creation, or the path is invalid for the OS.","commonSituations":"The output file path is configured with a relative path that resolves to an unexpected location. A parent path component (e.g., 'build/native-image') conflicts with a file of the same name. The build output directory is on a network mount or read-only volume. The Gradle daemon process lacks write permission to the configured output location.","solutions":["Check if any path component of the output file's parent is a regular file rather than a directory: inspect the path manually.","Ensure the Gradle daemon process has write permissions to the output location: ls -la on the parent directory chain.","If using a custom output file, set it to an absolute path within the project's build directory: getOutputFile().set(project.getLayout().getBuildDirectory().file('native-image/output')).","Run a clean build to clear any stale file/directory conflicts: ./gradlew clean."],"exampleFix":"// before\nnativeImageBuild {\n    outputFile = file('/opt/native-images/app') // parent /opt/native-images may not exist or be read-only\n}\n\n// after\nnativeImageBuild {\n    outputFile = layout.buildDirectory.file('native-image/app') // within writable build dir\n}","handlingStrategy":"validation","validationCode":"// Validate output directory before task execution\nFile outputDir = outputFile.getParentFile();\nif (outputDir != null && !outputDir.exists()) {\n    if (!outputDir.getCanonicalPath().startsWith(project.getBuildDir().getCanonicalPath())) {\n        throw new GradleException(\"Output directory is outside build dir: \" + outputDir);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure output files within the project build directory.","Run ./gradlew clean before builds to remove stale path conflicts.","Ensure the Gradle daemon user has write permissions to the build directory."],"tags":["native-image","filesystem","build-task","io"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}