{"record":{"id":"e98ea5897c40f8fb","repo":"apache/hadoop","slug":"source-src-destination-dst-both-should-be-ei","errorCode":null,"errorMessage":"Source ${src} Destination ${dst} both should be either file or directory","messagePattern":"Source (.+?) Destination (.+?) both should be either file or directory","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java","lineNumber":1695,"sourceCode":"\n    boolean overwrite = false;\n    if (null != options) {\n      for (Rename option : options) {\n        if (option == Rename.OVERWRITE) {\n          overwrite = true;\n        }\n      }\n    }\n\n    FileStatus dstStatus;\n    try {\n      dstStatus = getFileLinkStatus(dst);\n    } catch (IOException e) {\n      dstStatus = null;\n    }\n    if (dstStatus != null) {\n      if (srcStatus.isDirectory() != dstStatus.isDirectory()) {\n        throw new IOException(\"Source \" + src + \" Destination \" + dst\n            + \" both should be either file or directory\");\n      }\n      if (!overwrite) {\n        throw new FileAlreadyExistsException(\"rename destination \" + dst\n            + \" already exists.\");\n      }\n      // Delete the destination that is a file or an empty directory\n      if (dstStatus.isDirectory()) {\n        FileStatus[] list = listStatus(dst);\n        if (list != null && list.length != 0) {\n          throw new IOException(\n              \"rename cannot overwrite non empty destination directory \" + dst);\n        }\n      }\n      delete(dst, false);\n    } else {\n      final Path parent = dst.getParent();\n      final FileStatus parentStatus = getFileStatus(parent);","sourceCodeStart":1677,"sourceCodeEnd":1713,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java#L1677-L1713","documentation":"Inside the deprecated options-aware rename: the destination exists but srcStatus.isDirectory() != dstStatus.isDirectory(), so the operation is rejected with IOException('Source ... Destination ... both should be either file or directory'). Overwriting cannot change the node type, so this check runs before the OVERWRITE flag is even honored.","triggerScenarios":"rename(file -> existing directory) or rename(directory -> existing file), with or without Rename.OVERWRITE.","commonSituations":"Job reruns where a previous run's output changed shape (single marker file vs directory of part-files); publish code renaming a directory onto a path that used to hold a file.","solutions":["Make the types agree: delete the mismatched destination first (delete(dst, true) for directories)","Verify dst's type before relying on OVERWRITE for file-replaces-file semantics","Branch on the two statuses yourself so the mismatch is a handled case, not an exception"],"exampleFix":"// before\nfs.rename(srcDir, dstFile, Rename.OVERWRITE); // type mismatch\n\n// after\nFileStatus d = fs.exists(dst) ? fs.getFileStatus(dst) : null;\nif (d != null && d.isDirectory() != fs.getFileStatus(src).isDirectory()) {\n  fs.delete(dst, true);\n}\nfs.rename(src, dst, Rename.OVERWRITE);","handlingStrategy":"validation","validationCode":"FileStatus s = fs.getFileStatus(src);\nif (fs.exists(dst)) {\n  FileStatus d = fs.getFileStatus(dst);\n  if (d.isDirectory() != s.isDirectory()) {\n    fs.delete(dst, true); // types must agree before OVERWRITE can apply\n  }\n}\nfs.rename(src, dst, Rename.OVERWRITE);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide explicitly what happens when dst exists","Keep output layouts stable across runs (file vs directory shape)","Delete mismatched destinations before overwrite renames"],"tags":["hadoop","filesystem","rename","type-mismatch"],"backgroundTag":"rename-type-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}