apache/druid · error · IOE
Cannot create directory [%s]
Error message
Cannot create directory [%s]
What it means
FileUtils.mkdirp throws this IOException when File.mkdirs() fails and the directory still does not exist afterwards. Because two concurrent mkdirs calls cannot both succeed, the code tolerates races via the isDirectory() check; this error means creation genuinely failed (permissions, path component issues, etc.).
Source
Thrown at processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java:513
}
}
/**
* Create "directory" and all intermediate directories as needed. If the directory is successfully created, or already
* exists, returns quietly. Otherwise, throws an IOException.
*
* Simpler to use than {@link File#mkdirs()}, and more reliable since it is safe from races where two threads try
* to create the same directory at the same time.
*
* The name is inspired by UNIX {@code mkdir -p}, which has the same behavior.
*/
@SuppressForbidden(reason = "File#mkdirs")
public static void mkdirp(final File directory) throws IOException
{
// isDirectory check after mkdirs is necessary in case of concurrent calls to mkdirp, because two concurrent
// calls to mkdirs cannot both succeed.
if (!directory.mkdirs() && !directory.isDirectory()) {
throw new IOE("Cannot create directory [%s]", directory);
}
}
/**
* Equivalent to {@link org.apache.commons.io.FileUtils#deleteDirectory(File)}. Exists here mostly so callers
* can avoid dealing with our FileUtils and the Commons FileUtils having the same name.
*/
@SuppressForbidden(reason = "FilesUtils#deleteDirectory")
public static void deleteDirectory(final File directory) throws IOException
{
org.apache.commons.io.FileUtils.deleteDirectory(directory);
}
/**
* Deletes {@code directory} (recursively, like {@link #deleteDirectory(File)}), then walks up deleting each
* now-empty ancestor directory, stopping at the first non-empty ancestor or when {@code stopAt} is reached,
* whichever comes first. {@code stopAt} itself is never deleted, so callers can pass a base directory that must
* survive.View on GitHub (pinned to 9b90983fd2)
Solutions
- Check permissions on each path component and create the parent chain manually if needed
- Verify no regular file exists at the target path; remove or rename it
- Ensure the process user owns or can write to the parent directory
- Catch the IOException and fall back to an alternate configured directory
- Re-check the configured path for typos (e.g. wrong mount point)
Example fix
// before
FileUtils.mkdirp(new File("/druid/segment-cache")); // /druid owned by root
// after
Files.createDirectories(Paths.get("/druid/segment-cache")); // pre-created with correct owner
FileUtils.mkdirp(new File("/druid/segment-cache")); Defensive patterns
Strategy: try-catch
Validate before calling
File dir = new File(path);
File parent = dir.getAbsoluteFile().getParentFile();
if (parent != null && !parent.canWrite()) throw new IllegalStateException("Cannot create " + path + ": parent not writable");
if (dir.isFile()) throw new IllegalStateException("Path is a file, not a directory: " + path); Type guard
static boolean canMkdirp(File dir) {
return dir != null && !dir.isFile()
&& (dir.isDirectory() || (dir.getAbsoluteFile().getParentFile() != null && dir.getAbsoluteFile().getParentFile().canWrite()));
} Try / catch
try {
FileUtils.mkdirp(dir);
} catch (IOException e) {
throw new RuntimeException("Failed to create directory " + dir + ": " + e.getMessage(), e);
} Prevention
- Pre-create the parent directory chain at provisioning/deployment time with correct ownership
- Ensure no stray regular file occupies the target path
- Run the service under a user that owns or can write to the parent directory
- Handle concurrent startup races — mkdirp tolerates them, but permission errors do not resolve themselves
When it happens
Trigger: Calling FileUtils.mkdirp(directory) where some path component is missing and cannot be created, the target or an intermediate component is a regular file, or the OS denies creation permissions.
Common situations: First startup with segment cache or task dirs on a path the druid user cannot create; a stale file occupying the directory path; typo'd directory configuration creating deeply nested invalid paths; read-only volume.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- Cannot create tempDir [%s] for google storage connector
- Cannot list directory [%s]
- Could not create temp distribution directory.
- Could not close channel for level [%d] and rank [%d]
- Unable to close channel for name :
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/8cbcd896e5b5e256.
Report an issue: GitHub.