{"record":{"id":"5b68e20e83d2f992","repo":"apache/hadoop","slug":"cannot-append-to-directory-path-already","errorCode":null,"errorMessage":"\"Cannot append to directory \" + path + \"; already exists as a directory.\"","messagePattern":"\"Cannot append to directory \" \\+ path \\+ \"; already exists as a directory\\.\"","errorType":"exception","errorClass":"FileAlreadyExistsException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAppendOp.java","lineNumber":98,"sourceCode":"   * @return the last block with status\n   */\n  static LastBlockWithStatus appendFile(final FSNamesystem fsn,\n      final String srcArg, final FSPermissionChecker pc, final String holder,\n      final String clientMachine, final boolean newBlock,\n      final boolean logRetryCache) throws IOException {\n    assert fsn.hasWriteLock(RwLockMode.GLOBAL);\n\n    final LocatedBlock lb;\n    final FSDirectory fsd = fsn.getFSDirectory();\n    final INodesInPath iip;\n    fsd.writeLock();\n    try {\n      iip = fsd.resolvePath(pc, srcArg, DirOp.WRITE);\n      // Verify that the destination does not exist as a directory already\n      final INode inode = iip.getLastINode();\n      final String path = iip.getPath();\n      if (inode != null && inode.isDirectory()) {\n        throw new FileAlreadyExistsException(\"Cannot append to directory \"\n            + path + \"; already exists as a directory.\");\n      }\n      if (fsd.isPermissionEnabled()) {\n        fsd.checkPathAccess(pc, iip, FsAction.WRITE);\n      }\n\n      if (inode == null) {\n        throw new FileNotFoundException(\n            \"Failed to append to non-existent file \" + path + \" for client \"\n                + clientMachine);\n      }\n      final INodeFile file = INodeFile.valueOf(inode, path, true);\n\n      if (file.isStriped() && !newBlock) {\n        throw new UnsupportedOperationException(\n            \"Append on EC file without new block is not supported. Use \"\n                + CreateFlag.NEW_BLOCK + \" create flag while appending file.\");\n      }","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirAppendOp.java#L80-L116","documentation":"FSDirAppendOp.appendFile throws FileAlreadyExistsException when the append target resolves to an existing directory. HDFS append only extends an existing file - it never creates or replaces paths - so a directory target is rejected right after resolvePath and before permission checks.","triggerScenarios":"ClientProtocol.append / DistributedFileSystem.append(path) or 'hdfs dfs -appendToFile ... <dst>' where dst is a directory: an output path like /jobs/out that an earlier run created with mkdirs, or a path whose last component exists as a directory.","commonSituations":"Job drivers that append to a 'current' file whose path the previous stage mkdirs()-ed; path construction bugs pointing at the directory instead of a file inside it; output-committers pre-creating the _temporary target path.","solutions":["Check fs.getFileStatus(path).isDirectory() before calling append and fail fast with a clear message.","Point the append at a file under the directory (e.g. /jobs/out/part-0) and make sure no upstream stage mkdirs() that exact file path.","If the directory is stale output from an earlier layout, delete or rename it before writing."],"exampleFix":"// before\nFSDataOutputStream out = fs.append(path);\n\n// after\nif (fs.exists(path) && fs.getFileStatus(path).isDirectory()) {\n  throw new IllegalArgumentException(path + \" is a directory; append to a file inside it\");\n}\nFSDataOutputStream out = fs.append(path);","handlingStrategy":"validation","validationCode":"static void assertAppendTargetIsFile(FileSystem fs, Path p) throws IOException {\n  if (fs.exists(p) && fs.getFileStatus(p).isDirectory()) {\n    throw new IllegalArgumentException(p + \" is a directory; append to a file path under it\");\n  }\n}","typeGuard":"static boolean isAppendablePath(FileSystem fs, Path p) throws IOException {\n  return !fs.exists(p) || !fs.getFileStatus(p).isDirectory(); // missing files fail later with FNFE\n}","tryCatchPattern":"try {\n  out = fs.append(path);\n} catch (FileAlreadyExistsException e) {\n  // append hit a directory: fix the path configuration, do not retry the same path\n}","preventionTips":["Never mkdirs() an exact path a later stage appends to; separate dir creation from file paths.","Validate output path templates once at job startup."],"tags":["hdfs","append","filesystem","namenode"],"backgroundTag":"path-is-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}