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

  1. Use deleteRecursively(path) when the target may be a directory.
  2. Check isDirectory before deleting and route accordingly in cleanup code.
  3. Fix path-building logic so only concrete file paths (not prefixes/parents) reach deleteFile.
  4. 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

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


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)