{"record":{"id":"155e2fcc2a10e7b4","repo":"apache/hadoop","slug":"path-file-is-a-directory","errorCode":null,"errorMessage":"Path {file} is a directory.","messagePattern":"Path (.+?) is a directory\\.","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java","lineNumber":284,"sourceCode":"   * @param path\n   * @return\n   */\n  private Path makeAbsolute(Path workDir, Path path) {\n    if (path.isAbsolute()) {\n      return path;\n    }\n    return new Path(workDir, path);\n  }\n\n  @Override\n  public FSDataInputStream open(Path file, int bufferSize) throws IOException {\n    FTPClient client = connect();\n    Path workDir = new Path(client.printWorkingDirectory());\n    Path absolute = makeAbsolute(workDir, file);\n    FileStatus fileStat = getFileStatus(client, absolute);\n    if (fileStat.isDirectory()) {\n      disconnect(client);\n      throw new FileNotFoundException(\"Path \" + file + \" is a directory.\");\n    }\n    client.allocate(bufferSize);\n    Path parent = absolute.getParent();\n    // Change to parent directory on the\n    // server. Only then can we read the\n    // file\n    // on the server by opening up an InputStream. As a side effect the working\n    // directory on the server is changed to the parent directory of the file.\n    // The FTP client connection is closed when close() is called on the\n    // FSDataInputStream.\n    client.changeWorkingDirectory(parent.toUri().getPath());\n    InputStream is = client.retrieveFileStream(file.getName());\n    FSDataInputStream fis = new FSDataInputStream(new FTPInputStream(is,\n        client, statistics));\n    if (!FTPReply.isPositivePreliminary(client.getReplyCode())) {\n      // The ftpClient is an inconsistent state. Must close the stream\n      // which in turn will logout and disconnect from FTP server\n      fis.close();","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java#L266-L302","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nFSDataInputStream in = fs.open(path); // path is a dir -> FileNotFoundException\n\n// after\nFileStatus st = fs.getFileStatus(path);\nif (st.isDirectory()) {\n  throw new IllegalArgumentException(\"Input is a directory: \" + path);\n}\nFSDataInputStream in = fs.open(path);","handlingStrategy":"validation","validationCode":"FileStatus st = fs.getFileStatus(path);\nif (st.isDirectory()) {\n  throw new IllegalArgumentException(\"Expected a file but got directory: \" + path);\n}\nFSDataInputStream in = fs.open(path);","typeGuard":"static boolean isRegularFile(FileSystem fs, Path p) throws IOException {\n  FileStatus st = fs.getFileStatus(p);\n  return st != null && st.isFile();\n}","tryCatchPattern":"try {\n  in = fs.open(path);\n} catch (FileNotFoundException e) {\n  // re-stat to distinguish 'is a directory' from truly missing\n  if (fs.exists(path) && fs.getFileStatus(path).isDirectory()) {\n    // handle wrong-type path\n  }\n}","preventionTips":["Validate input paths at job setup, not at first read","Do not assume FileNotFoundException only means missing file with FTPFileSystem — read the message"],"tags":["ftp","is-a-directory","open","file-not-found"],"backgroundTag":"is-a-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}