elastic/elasticsearch · error · IOException

Could not create directory: {packageDir}

Error message

Could not create directory: {packageDir}

What it means

Thrown by GenerateEsqlSpecTestsTask.generate() when the package directory for generated ES|QL spec test source files cannot be created. The task deletes the output directory, then derives a package path from the configured package name (converting dots to slashes) and calls mkdirs(). If mkdirs() returns false AND the directory does not exist afterward, it throws IOException.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/esql/GenerateEsqlSpecTestsTask.java:93

    @Input
    public abstract ListProperty<String> getVariantSpecFilePatterns();

    @OutputDirectory
    public abstract DirectoryProperty getOutputDirectory();

    @Inject
    public abstract FileSystemOperations getFileSystemOperations();

    @TaskAction
    public void generate() throws IOException {
        File outputDir = getOutputDirectory().getAsFile().get();
        getFileSystemOperations().delete(spec -> spec.delete(outputDir));

        String packageName = getPackageName().get();
        String packagePath = packageName.replace('.', '/');
        File packageDir = new File(outputDir, packagePath);
        if (packageDir.mkdirs() == false && packageDir.exists() == false) {
            throw new IOException("Could not create directory: " + packageDir);
        }

        List<String> prefixes = getVariantPrefixes().get();
        List<String> baseClasses = getVariantBaseClasses().get();
        List<String> allEncodedPatterns = getVariantSpecFilePatterns().get();
        if (prefixes.size() != baseClasses.size() || prefixes.size() != allEncodedPatterns.size()) {
            throw new IllegalStateException("variantPrefixes, variantBaseClasses, and variantSpecFilePatterns must have the same length");
        }

        File specDir = getSpecFilesDir().getAsFile().get();
        File[] specFiles = specDir.listFiles((dir, name) -> name.endsWith(".csv-spec"));
        if (specFiles == null) {
            return;
        }
        Arrays.sort(specFiles);
        for (File specFile : specFiles) {
            String specFileName = specFile.getName();
            String baseName = specFileName.substring(0, specFileName.length() - ".csv-spec".length());

View on GitHub (pinned to db6a809a66)

Solutions

  1. Run ./gradlew clean to remove stale output directories that may conflict with file-typed path components.
  2. Verify the packageName property resolves to a valid path: ensure it contains no path separators or invalid characters.
  3. Ensure the Gradle daemon has write permissions to the output directory location.
  4. Check that getOutputDirectory() is set to a writable location within the project's build directory.
Defensive patterns

Strategy: validation

Validate before calling

// Validate output directory writability
File outputDir = getOutputDirectory().getAsFile().get();
File parent = outputDir.getParentFile();
if (parent != null && parent.exists() && !parent.canWrite()) {
    throw new GradleException("Cannot write to output directory: " + outputDir);
}

Prevention

When it happens

Trigger: The output directory is deleted via FileSystemOperations.delete, then packageDir.mkdirs() is called. mkdirs() returns false if a parent path component is a regular file, if permissions are insufficient, or if the path is read-only. The check `mkdirs() == false && exists() == false` handles the race where mkdirs returns false because the directory already existed (created by a concurrent process), but a genuine failure propagates.

Common situations: The output directory path conflicts with a file of the same name left by a previous incomplete build. The build runs on a read-only filesystem or a CI agent with restricted write access. The package name property is misconfigured, producing a path that resolves outside the project build directory.

Related errors


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