apache/hadoop · error · FileNotFoundException
'{}' is a directory
Error message
'{}' is a directory What it means
open() stats the path and refuses directories with FileNotFoundException("'<path>' is a directory"). COS has no directory payload to read, so opening a directory key — including the 0-byte marker objects CosN itself creates — is treated as 'nothing to read', mirroring LocalFileSystem behavior.
Source
Thrown at hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNFileSystem.java:592
if (LOG.isDebugEnabled()) {
LOG.debug("Make directory: [{}] in COS.", f);
}
String folderPath = pathToKey(makeAbsolute(f));
if (!folderPath.endsWith(PATH_DELIMITER)) {
folderPath += PATH_DELIMITER;
}
store.storeEmptyFile(folderPath);
}
return true;
}
@Override
public FSDataInputStream open(Path f, int bufferSize) throws IOException {
FileStatus fs = getFileStatus(f); // will throw if the file doesn't
// exist
if (fs.isDirectory()) {
throw new FileNotFoundException("'" + f + "' is a directory");
}
LOG.info("Open the file: [{}] for reading.", f);
Path absolutePath = makeAbsolute(f);
String key = pathToKey(absolutePath);
long fileSize = store.getFileLength(key);
return new FSDataInputStream(new BufferedFSInputStream(
new CosNInputStream(this.getConf(), store, statistics, key, fileSize,
this.boundedIOThreadPool), bufferSize));
}
@Override
public boolean rename(Path src, Path dst) throws IOException {
LOG.debug("Rename source path: [{}] to dest path: [{}].", src, dst);
// Renaming the root directory is not allowed
if (src.isRoot()) {
LOG.debug("Cannot rename the root directory of a filesystem.");
return false;View on GitHub (pinned to 2add963021)
Solutions
- Filter glob results: only open statuses where isFile() is true.
- If a file was expected, inspect getFileStatus(p) — the path is actually a directory.
- Use fs.listStatus(dir) to enumerate children instead of open().
Example fix
// before
for (FileStatus s : fs.globStatus(new Path('/in/*'))) {
FSDataInputStream in = fs.open(s.getPath()); // throws on directories
}
// after
for (FileStatus s : fs.globStatus(new Path('/in/*'))) {
if (s.isFile()) {
FSDataInputStream in = fs.open(s.getPath());
}
} Defensive patterns
Strategy: validation
Validate before calling
FileStatus st = fs.getFileStatus(p);
if (st.isDirectory()) {
for (FileStatus child : fs.listStatus(p)) { /* enumerate instead of open */ }
} else {
FSDataInputStream in = fs.open(p);
} Type guard
static boolean isOpenableFile(FileStatus st) {
return st.isFile();
} Try / catch
try {
return fs.open(p);
} catch (FileNotFoundException e) {
if (e.getMessage() != null && e.getMessage().endsWith('is a directory')) {
// caller passed a directory: fall back to listing
return null; // or throw a clearer domain error
}
throw e;
} Prevention
- Always branch on FileStatus.isFile() before open
- Glob results include directories: filter them
- Cat/read utilities should check the status type first
When it happens
Trigger: fs.open(dirPath); opening a path that exists only as an implicit directory (common prefixes derived from children); hadoop fs -cat on a directory; code that globs a pattern and open()s every result without filtering.
Common situations: Glob 'cosn://bucket/*' then open each status including directories; passing a directory to a reader that expects a file; trailing-slash confusion where a directory path is handed to open unchanged.
Related errors
- No such file or directory '{}'
- {} : not a file in {}
- Path {file} is a directory.
- File {} not found.
- key + ": No such file or directory."
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/93cb115d38b28925.
Report an issue: GitHub.