apache/hadoop · error · IOException

Cannot rename source: {absoluteSrc} to {absoluteDst} -only s

Error message

Cannot rename source: {absoluteSrc} to {absoluteDst} -only same directory renames are supported

What it means

FTP's RNFR/RNTO can only rename an entry within its parent directory. FTPFileSystem enforces this: if the parent directories of the absolute source and destination differ (compared as parent URIs), it throws IOException("Cannot rename source ... - only same directory renames are supported") without contacting the server.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:696

    }
    if (isDirectory(absoluteDst)) {
      // destination is a directory: rename goes underneath it with the
      // source name
      absoluteDst = new Path(absoluteDst, absoluteSrc.getName());
    }
    if (exists(client, absoluteDst)) {
      throw new FileAlreadyExistsException("Destination path " + dst
          + " already exists");
    }
    URI parentSrc = absoluteSrc.getParent().toUri();
    URI parentDst = absoluteDst.getParent().toUri();
    if (isParentOf(absoluteSrc, absoluteDst)) {
      throw new IOException("Cannot rename " + absoluteSrc + " under itself"
      + " : "+ absoluteDst);
    }

    if (!parentSrc.toString().equals(parentDst.toString())) {
      throw new IOException("Cannot rename source: " + absoluteSrc
          + " to " + absoluteDst
          + " -"+ E_SAME_DIRECTORY_ONLY);
    }
    String from = absoluteSrc.getName();
    String to = absoluteDst.getName();
    client.changeWorkingDirectory(parentSrc.getPath());
    boolean renamed = client.rename(from, to);
    return renamed;
  }

  @Override
  public Path getWorkingDirectory() {
    // Return home directory always since we do not maintain state.
    return getHomeDirectory();
  }

  @Override
  public Path getHomeDirectory() {

View on GitHub (pinned to 2add963021)

Solutions

  1. Implement move as copy + delete: FileUtil.copy(fs, src, fs, dst, true, conf)
  2. If you only mean to rename, keep both paths inside the same parent directory
  3. Normalize both parents (makeQualified + getParent().toUri()) before assuming they are equal or different
  4. Stage data on HDFS/local when frequent moves are needed; treat FTP purely as a transfer source/sink

Example fix

// before
fs.rename(new Path("/incoming/f.dat"), new Path("/archive/f.dat"));  // same-dir only -> IOException

// after
boolean moved = FileUtil.copy(fs, src, fs, dst, /*deleteSource*/ true, conf);
if (!moved) {
  throw new IOException("copy-move failed: " + src + " -> " + dst);
}
Defensive patterns

Strategy: validation

Validate before calling

// only same-parent renames are supported on ftp://
if (!src.getParent().equals(dst.getParent())) {
  boolean moved = FileUtil.copy(fs, src, fs, dst, /*deleteSource*/ true, conf);
  if (!moved) { throw new IOException("copy-move failed: " + src); }
} else {
  fs.rename(src, dst);
}

Try / catch

catch IOException containing "only same directory renames are supported" and fall back to FileUtil.copy with deleteSource=true.

Prevention

When it happens

Trigger: rename("/dir1/file", "/dir2/file") or any dst whose parent differs from src's parent, including "move into another directory" intentions; also URI normalization differences (trailing slash, encoding) making equal parents compare unequal as strings.

Common situations: Porting code from LocalFileSystem/HDFS where cross-directory rename works; ingest flows trying to "move" files between FTP directories over an ftp:// URL; path strings assembled with inconsistent encoding or slashes so the parent string comparison fails even in the same directory.

Related errors


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