apache/druid · error · org.apache.druid.java.util.common.IAE
Cannot list contents of
Error message
Cannot list contents of [%s] since it is not a directory
What it means
LocalFileStorageConnector.listDir throws this IllegalArgumentException when the given path resolves to an existing file rather than a directory. The connector first checks existence, then verifies the path is a directory before calling File.listFiles(). It is a caller-input validation error.
Solutions
- Fix the caller to pass a directory path, not a file path
- Verify the path on disk with ls -la and correct the directory layout
- Add an isDirectory check in the caller before invoking listDir
Example fix
// before
connector.listDir("taskDir/task-123/index.zip");
// after
connector.listDir("taskDir/task-123"); Defensive patterns
Strategy: validation
Validate before calling
File dir = new File(basePath, dirName);
if (!dir.isDirectory()) {
throw new IllegalArgumentException(dirName + " is not a directory");
}
connector.listDir(dirName); Type guard
static boolean isDirectory(File f) { return f != null && f.isDirectory(); } Try / catch
try { connector.listDir(dir); } catch (IllegalArgumentException e) { logger.error(e, "not a directory: %s", dir); } Prevention
- Validate the path with File.isDirectory() before calling listDir
- Never pass full file paths (e.g. index.zip) to directory-listing APIs
- Log the resolved absolute path when configuring directory roots
When it happens
Trigger: Calling listDir(dirName) with a path that points to a regular file (or symlink to a file) that exists under the connector's basePath. Example: listDir("segments/wiki/2010-01-01T00:00:00.000Z_2010-01-01T01:00:00.000Z/0") where the final element is a file, not a folder.
Common situations: Passing a full file path (including segment descriptor file) to a directory-listing API; a config that mixes up the logs/lock/task directory root with a file inside it; stale directory replaced by a file after upgrade or manual cleanup.
Related errors
- A-Not-B requires at least 1 sketch
- BloomKFilters are not compatible for merging. this
- Bucket index out of range (0, )
- Caching is not supported. Check `isCacheable` before…
- Cannot add files of the same name, already have
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/0d5df886e41b870d.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/storage/local/LocalFileStorageConnector.java:161
* @param dirName path
* @throws IOException thrown in case of errors.
*/
@Override
public void deleteRecursively(String dirName) throws IOException
{
log.debug("Deleting directory at path: [%s]", dirName);
FileUtils.deleteDirectory(fileWithBasePath(dirName));
}
@Override
public Iterator<String> listDir(String dirName)
{
File directory = fileWithBasePath(dirName);
if (!directory.exists()) {
throw new IAE("No directory exists on path [%s]", dirName);
}
if (!directory.isDirectory()) {
throw new IAE("Cannot list contents of [%s] since it is not a directory", dirName);
}
File[] files = directory.listFiles();
if (files == null) {
throw new ISE("Unable to fetch the file list from the path [%s]", dirName);
}
return Arrays.stream(files).map(File::getName).iterator();
}
public File getBasePath()
{
return basePath;
}
private File fileWithBasePath(String path)
{
return new File(basePath, path);
}
View on GitHub (pinned to 9b90983fd2)