apache/hadoop · error · FileNotFoundException
Path {file} is a directory.
Error message
Path {file} is a directory. What it means
FTPFileSystem.open() stats the target before issuing RETR and refuses to open a directory as a stream. It throws FileNotFoundException even though the path exists — FTPFileSystem has no directory-stream semantics, and the message distinguishes this from a genuinely missing file.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:284
* @param path
* @return
*/
private Path makeAbsolute(Path workDir, Path path) {
if (path.isAbsolute()) {
return path;
}
return new Path(workDir, path);
}
@Override
public FSDataInputStream open(Path file, int bufferSize) throws IOException {
FTPClient client = connect();
Path workDir = new Path(client.printWorkingDirectory());
Path absolute = makeAbsolute(workDir, file);
FileStatus fileStat = getFileStatus(client, absolute);
if (fileStat.isDirectory()) {
disconnect(client);
throw new FileNotFoundException("Path " + file + " is a directory.");
}
client.allocate(bufferSize);
Path parent = absolute.getParent();
// Change to parent directory on the
// server. Only then can we read the
// file
// on the server by opening up an InputStream. As a side effect the working
// directory on the server is changed to the parent directory of the file.
// The FTP client connection is closed when close() is called on the
// FSDataInputStream.
client.changeWorkingDirectory(parent.toUri().getPath());
InputStream is = client.retrieveFileStream(file.getName());
FSDataInputStream fis = new FSDataInputStream(new FTPInputStream(is,
client, statistics));
if (!FTPReply.isPositivePreliminary(client.getReplyCode())) {
// The ftpClient is an inconsistent state. Must close the stream
// which in turn will logout and disconnect from FTP server
fis.close();View on GitHub (pinned to 2add963021)
Solutions
- Check fs.getFileStatus(path).isDirectory() before open() and listStatus() or fail with a clear message
- Validate user-configured input paths at job setup time
- In the catch handler, re-stat the path to distinguish 'is a directory' from 'missing' before reporting
Example fix
// before
FSDataInputStream in = fs.open(path); // path is a dir -> FileNotFoundException
// after
FileStatus st = fs.getFileStatus(path);
if (st.isDirectory()) {
throw new IllegalArgumentException("Input is a directory: " + path);
}
FSDataInputStream in = fs.open(path); Defensive patterns
Strategy: validation
Validate before calling
FileStatus st = fs.getFileStatus(path);
if (st.isDirectory()) {
throw new IllegalArgumentException("Expected a file but got directory: " + path);
}
FSDataInputStream in = fs.open(path); Type guard
static boolean isRegularFile(FileSystem fs, Path p) throws IOException {
FileStatus st = fs.getFileStatus(p);
return st != null && st.isFile();
} Try / catch
try {
in = fs.open(path);
} catch (FileNotFoundException e) {
// re-stat to distinguish 'is a directory' from truly missing
if (fs.exists(path) && fs.getFileStatus(path).isDirectory()) {
// handle wrong-type path
}
} Prevention
- Validate input paths at job setup, not at first read
- Do not assume FileNotFoundException only means missing file with FTPFileSystem — read the message
When it happens
Trigger: fs.open(path) where path is a directory on the FTP server: user-supplied or glob-resolved input path pointing at a directory; a file path reused as a directory by another writer.
Common situations: Input path configuration pointing at a directory instead of a file; code that assumes FileNotFoundException can only mean 'missing file' and mis-handles 'is a directory'; tools that pass through whatever path the user typed.
Related errors
- '{}' is a directory
- {} : not a file in {}
- File {file} does not exist.
- Source path {src} does not exist
- Cannot open filename {}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/155e2fcc2a10e7b4.
Report an issue: GitHub.