apache/hadoop · error · IOException

Source '{srcFile}' and destination '{destFile}' are the same

Error message

Source '{srcFile}' and destination '{destFile}' are the same

What it means

Guard clause of Storage.nativeCopyFileUnbuffered: getCanonicalPath() of source and destination are equal, so the copy would read and write the same file. Canonical comparison resolves symlinks and relative segments, catching indirect self-copies a plain equals would miss.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/Storage.java:1339

   * @throws IOException if source or destination is invalid
   * @throws IOException if an IO error occurs during copying
   */
  public static void nativeCopyFileUnbuffered(File srcFile, File destFile,
      boolean preserveFileDate) throws IOException {
    if (srcFile == null) {
      throw new NullPointerException("Source must not be null");
    }
    if (destFile == null) {
      throw new NullPointerException("Destination must not be null");
    }
    if (srcFile.exists() == false) {
      throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
    }
    if (srcFile.isDirectory()) {
      throw new IOException("Source '" + srcFile + "' exists but is a directory");
    }
    if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
      throw new IOException("Source '" + srcFile + "' and destination '" +
          destFile + "' are the same");
    }
    File parentFile = destFile.getParentFile();
    if (parentFile != null) {
      if (!parentFile.mkdirs() && !parentFile.isDirectory()) {
        throw new IOException("Destination '" + parentFile
            + "' directory cannot be created");
      }
    }
    if (destFile.exists()) {
      if (FileUtil.canWrite(destFile) == false) {
        throw new IOException("Destination '" + destFile
            + "' exists but is read-only");
      } else {
        if (destFile.delete() == false) {
          throw new IOException("Destination '" + destFile
              + "' exists but cannot be deleted");
        }

View on GitHub (pinned to 2add963021)

Solutions

  1. Write to a distinct destination (e.g. a temp file in the same directory) and move it afterwards
  2. Skip the copy when the canonical paths match instead of erroring
  3. Fix the configuration lookup that produced the identical destination

Example fix

// before
Storage.nativeCopyFileUnbuffered(src, dst == null ? src : dst, true);
// after
if (src.getCanonicalPath().equals(dst.getCanonicalPath())) return;
Storage.nativeCopyFileUnbuffered(src, dst, true);
Defensive patterns

Strategy: validation

Validate before calling

if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
  return; // self-copy is a no-op, not an error
}

Prevention

When it happens

Trigger: src and dest are the same path, or differ only via symlink, '..', or case-insensitive filesystem spelling; backup logic that falls back to the original path when the backup path is unset.

Common situations: Defaulted backup/destination config that silently equals the source; symlinked storage dirs (dst is a symlink to src); rotating-file logic that degrades to no-op paths.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/f36a81bf360288db. Report an issue: GitHub.