{"record":{"id":"08091a9d218a4cb8","repo":"apache/hadoop","slug":"can-t-open-because-it-is-a-directory","errorCode":null,"errorMessage":"Can't open {} because it is a directory","messagePattern":"Can't open (.+?) because it is a directory","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSFileSystem.java","lineNumber":659,"sourceCode":"  protected URI canonicalizeUri(final URI rawUri) {\n    return OBSLoginHelper.canonicalizeUri(rawUri, getDefaultPort());\n  }\n\n  /**\n   * Open an FSDataInputStream at the indicated Path.\n   *\n   * @param f          the file path to open\n   * @param bufferSize the size of the buffer to be used\n   * @return the FSDataInputStream for the file\n   * @throws IOException on any failure to open the file\n   */\n  @Override\n  public FSDataInputStream open(final Path f, final int bufferSize)\n      throws IOException {\n    LOG.debug(\"Opening '{}' for reading.\", f);\n    final FileStatus fileStatus = getFileStatus(f);\n    if (fileStatus.isDirectory()) {\n      throw new FileNotFoundException(\n          \"Can't open \" + f + \" because it is a directory\");\n    }\n\n    return new FSDataInputStream(\n        new OBSInputStream(bucket, OBSCommonUtils.pathToKey(this, f),\n            fileStatus.getLen(),\n            obs, statistics, readAheadRange, this));\n  }\n\n  /**\n   * Create an FSDataOutputStream at the indicated Path with write-progress\n   * reporting.\n   *\n   * @param f           the file path to create\n   * @param permission  the permission to set\n   * @param overwrite   if a file with this name already exists, then if true,\n   *                    the file will be overwritten, and if false an error will\n   *                    be thrown","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSFileSystem.java#L641-L677","documentation":"OBSFileSystem.open(Path, int) resolves the path's FileStatus and refuses to open directories: if isDirectory() is true it throws FileNotFoundException('Can't open <path> because it is a directory'). In object stores a 'directory' is a marker (zero-byte key ending in '/') or an implied prefix, which has no readable content, so the connector fails fast with the standard 'not a file' signal rather than returning an empty stream. This matches the contract of FileSystem.open for other object-store implementations.","triggerScenarios":"Calling fs.open() on a path created with fs.mkdirs() or marked by a directory placeholder object; opening a path that a previous step created as a directory marker; glob/rename logic that resolves a directory where a file was expected.","commonSituations":"Pipelines where the same path is used as both output directory (MapReduce/Spark output committers create directories) and later opened as a file; racing writers where one creates the parent structure while another opens the leaf path; confusing 'directory exists' checks with 'file exists' checks before open.","solutions":["Check getFileStatus(f).isFile() (or use fs.exists plus isFile) before calling open","Fix the upstream path construction — usually the code built a directory path where the file key was intended (trailing slash, wrong join)","If the path may legitimately be either, branch on isDirectory() and read only in the file case","Delete the stray directory marker if it was created by mistake, then write/open the file key"],"exampleFix":"// before\nFSDataInputStream in = fs.open(new Path(\"/data/out\")); // if /data/out is a dir -> FileNotFoundException\n\n// after\nPath p = new Path(\"/data/out\");\nif (!fs.getFileStatus(p).isFile()) {\n  throw new IllegalArgumentException(\"expected a file at \" + p);\n}\nFSDataInputStream in = fs.open(p);","handlingStrategy":"validation","validationCode":"FileStatus st = fs.getFileStatus(f);\nif (st.isDirectory()) {\n  throw new IllegalArgumentException(\"cannot open a directory: \" + f);\n}\nFSDataInputStream in = fs.open(f, bufferSize);","typeGuard":null,"tryCatchPattern":"try {\n  return fs.open(f, bufferSize);\n} catch (FileNotFoundException e) {\n  if (String.valueOf(e.getMessage()).contains(\"because it is a directory\")) {\n    // path bug: the target is a directory; fix path resolution upstream\n  }\n  // genuine missing file handling\n  throw e;\n}","preventionTips":["Always check getFileStatus(...).isFile() before open","Distinguish exists() from isFile() in path validation helpers","Never reuse an output-directory path as an input file path"],"tags":["path-misuse","file-vs-directory","io","hadoop-obs"],"backgroundTag":"open-on-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}