apache/druid · error · org.apache.druid.java.util.common.IAE
Found a directory on path
Error message
Found a directory on path[%s]. Please use deleteRecursively to delete dirs
What it means
LocalFileStorageConnector.deleteFile only deletes regular files; if the path resolves to a directory it throws IAE telling the caller to use deleteRecursively instead. This guards against accidentally attempting Files.delete on directories, which would fail and could remove data unexpectedly.
Solutions
- Use deleteRecursively(path) when the target may be a directory.
- Check isDirectory before deleting and route accordingly in cleanup code.
- Fix path-building logic so only concrete file paths (not prefixes/parents) reach deleteFile.
- Add a pre-delete validation step in bulk cleanup jobs to skip or recurse into directories.
Example fix
// before
connector.deleteFile("export/2024/"); // directory
// after
File target = new File(basePath, "export/2024/");
if (target.isDirectory()) {
connector.deleteRecursively("export/2024/");
} else {
connector.deleteFile("export/2024/");
} Defensive patterns
Strategy: validation
Validate before calling
File f = new File(basePath, path);
if (f.isDirectory()) { connector.deleteRecursively(path); } else if (f.exists()) { connector.deleteFile(path); } Type guard
boolean isRegularFile(String p) { File f = new File(basePath, p); return f.exists() && !f.isDirectory(); } Try / catch
try { connector.deleteFile(path); } catch (IllegalArgumentException e) { connector.deleteRecursively(path); } Prevention
- Only pass file paths (not prefixes) to deleteFile.
- Prefer deleteRecursively for cleanup of unknown-shape trees.
- Normalize paths to avoid dropping the filename component.
- Log-and-skip directories in bulk delete loops instead of failing.
When it happens
Trigger: deleteFile(path) where the path under base path is an existing directory: passing a prefix/parent dir, empty-directory placeholders, or path computations that resolve to the base directory itself.
Common situations: Bulk delete jobs iterating paths that include directories; export destinations that create nested dirs whose parents are then passed to deleteFile; path normalization dropping the filename component.
Related errors
- No directory exists on path
- Group mapping [ ] does not exist.
- Invalid arguments for reading
- Requested delete lookup
- Requested delete of lookup
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/d833fa2d287577d7.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/storage/local/LocalFileStorageConnector.java:119
{
File toWrite = fileWithBasePath(path);
FileUtils.mkdirp(toWrite.getParentFile());
return Files.newOutputStream(toWrite.toPath());
}
/**
* Deletes the file present at the location basePath + path. Throws an exception in case a dir is encountered.
*
* @param path input path
* @throws IOException thrown in case of errors.
*/
@Override
public void deleteFile(String path) throws IOException
{
log.debug("Deleting file at path: [%s]", path);
File toDelete = fileWithBasePath(path);
if (toDelete.isDirectory()) {
throw new IAE(StringUtils.format(
"Found a directory on path[%s]. Please use deleteRecursively to delete dirs", path));
}
Files.delete(fileWithBasePath(path).toPath());
}
/**
* Deletes the files present at each basePath + path. Throws an exception in case a dir is encountered.
*
* @param paths list of path to delete
* @throws IOException thrown in case of errors.
*/
@Override
public void deleteFiles(Iterable<String> paths) throws IOException
{
for (String path : paths) {
log.debug("Deleting file at path: [%s]", path);
deleteFile(path);
}View on GitHub (pinned to 9b90983fd2)