{"record":{"id":"f42558718d1039fb","repo":"apache/hadoop","slug":"is-not-a-directory-f42558","errorCode":null,"errorMessage":"Is not a directory","messagePattern":"Is not a directory","errorType":"exception","errorClass":"PathIsNotDirectoryException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/CommandWithDestination.java","lineNumber":233,"sourceCode":"          dst = items[0];\n          break;\n        default:\n          throw new PathIOException(pathString, \"Too many matches\");\n      }\n    }\n  }\n\n  @Override\n  protected void processArguments(LinkedList<PathData> args)\n  throws IOException {\n    // if more than one arg, the destination must be a directory\n    // if one arg, the dst must not exist or must be a directory\n    if (args.size() > 1) {\n      if (!dst.exists) {\n        throw new PathNotFoundException(dst.toString());\n      }\n      if (!dst.stat.isDirectory()) {\n        throw new PathIsNotDirectoryException(dst.toString());\n      }\n    } else if (dst.exists) {\n      if (!dst.stat.isDirectory() && !overwrite) {\n        LOG.debug(\"Destination file exists: {}\", dst.stat);\n        throw new PathExistsException(dst.toString());\n      }\n    } else if (!dst.parentExists()) {\n      throw new PathNotFoundException(dst.toString())\n          .withFullyQualifiedPath(dst.path.toUri().toString());\n    }\n    super.processArguments(args);\n  }\n\n  @Override\n  protected void processPathArgument(PathData src)\n  throws IOException {\n    if (src.stat.isDirectory() && src.fs.equals(dst.fs)) {\n      PathData target = getTargetPath(src);","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/CommandWithDestination.java#L215-L251","documentation":"Thrown by CommandWithDestination.processArguments() when MULTIPLE source arguments are given and the destination exists but is a regular file. Multiple sources can only land inside a directory, so PathIsNotDirectoryException ('dst: Is not a directory') aborts before any transfer starts.","triggerScenarios":"'hdfs dfs -put a.txt b.txt /user/me/single.txt' where single.txt is an existing file; copying several files onto an existing file target with -cp; destination created earlier as a file by a first single-file copy.","commonSituations":"A first run created a file at the destination and later runs add more sources; scripts unconditionally appending sources; confusing Unix 'cat'-style merge semantics with copy semantics.","solutions":["Make the destination a directory: remove/rename the file, 'hdfs dfs -mkdir' the target, and rerun","If you want a single merged file, concatenate explicitly ('hdfs dfs -getmerge' or '-concat') instead of multi-source copy","Copy to a directory path with a trailing separator to state intent clearly"],"exampleFix":"# before\nhdfs dfs -put a.txt b.txt /user/me/out.bin\n# after\nhdfs dfs -rm /user/me/out.bin && hdfs dfs -mkdir /user/me/out.bin && hdfs dfs -put a.txt b.txt /user/me/out.bin","handlingStrategy":"validation","validationCode":"// before copying multiple sources, ensure destination is a directory, not a file\nif (fs.exists(dst) && !fs.getFileStatus(dst).isDirectory()) {\n  throw new IOException(\"multi-source copy needs a directory destination, but \" + dst + \" is a file\");\n}","typeGuard":"static boolean canAcceptMultipleSources(FileSystem fs, Path dst) throws IOException {\n  return !fs.exists(dst) ? false : fs.getFileStatus(dst).isDirectory();\n}","tryCatchPattern":"try {\n  shellRun(\"-put\", a, b, dst);\n} catch (PathIsNotDirectoryException e) {\n  // e.getPath() is the file-shaped destination; move it aside and make a real directory\n  shellRun(\"-mv\", dst, dst + \".bak\");\n  shellRun(\"-mkdir\", dst);\n  shellRun(\"-put\", a, b, dst);\n}","preventionTips":["Never reuse a single-file copy target for later multi-source runs","Use a trailing '/' on directory destinations to state intent","Use getmerge/concat for merging into one file instead of multi-source put/cp"],"tags":["hadoop","hdfs","destination","copy","directory-check","shell"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}