apache/hadoop · error · FTPException

Could not complete transfer, Reply Code -

Error message

Could not complete transfer, Reply Code - 

What it means

In close(), after the data stream ends the client must call completePendingCommand() to read the server's final reply; false means the server never confirmed success (e.g. 4xx/5xx or aborted transfer). The code then logs out, disconnects, and throws FTPException("Could not complete transfer, Reply Code - N"). The reply code is fetched after disconnect(), so treat it as the last known code and verify transfer completeness independently.

Source

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

    return result;
  }

  @Override
  public synchronized void close() throws IOException {
    if (closed) {
      return;
    }
    super.close();
    closed = true;
    if (!client.isConnected()) {
      throw new FTPException("Client not connected");
    }

    boolean cmdCompleted = client.completePendingCommand();
    client.logout();
    client.disconnect();
    if (!cmdCompleted) {
      throw new FTPException("Could not complete transfer, Reply Code - "
          + client.getReplyCode());
    }
  }

  // Not supported.

  @Override
  public boolean markSupported() {
    return false;
  }

  @Override
  public void mark(int readLimit) {
    // Do nothing
  }

  @Override
  public void reset() throws IOException {

View on GitHub (pinned to 2add963021)

Solutions

  1. Match the reply code with the FTP server log entry to find the true 4xx/5xx reason
  2. Verify the passive-mode port range is open end-to-end or switch active/passive mode to suit the network
  3. Validate size after read: compare bytes consumed (getPos()) with the file length from getFileStatus()
  4. Retry the full open/read/close cycle once — transient data-channel failures are common

Example fix

// before
try (FSDataInputStream in = fs.open(path)) {
  IOUtils.copyBytes(in, out, conf);   // close() may throw "Could not complete transfer"
}

// after
try (FSDataInputStream in = fs.open(path)) {
  IOUtils.copyBytes(in, out, conf);
  long read = in.getPos();
  long expected = fs.getFileStatus(path).getLen();
  if (read != expected) {
    throw new IOException("short read: " + read + " of " + expected);
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// verify completeness before trusting a completed copy
long read = in.getPos();
long expected = fs.getFileStatus(path).getLen();
if (read != expected) { /* treat as truncated; plan resume */ }

Try / catch

catch FTPException from close(); when the message starts with "Could not complete transfer", record getPos() as the resume point, reopen the stream, skip to that point, and continue reading — retry the whole cycle once before failing.

Prevention

When it happens

Trigger: Data connection breaking mid-RETR (passive port blocked, NAT timeout); server returning 426/550 during streaming; the reader closing early and abandoning the transfer; local disk/network errors aborting the download.

Common situations: Firewalls allowing control port 21 but blocking the passive data port range; large transfers hitting NAT idle timeouts; quota or permission changes on the server mid-session.

Related errors


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