apache/seatunnel · error · FTPException
Could not complete transfer, Reply Code - ${client.getReplyC
Error message
Could not complete transfer, Reply Code - ${client.getReplyCode()} What it means
Thrown by SeaTunnelFTPFileSystem when closing an FTP output stream: the FTP client sent the write commands, but the server did not report a successful completion of the pending data transfer. It means the file content may not have been fully persisted on the FTP server, so the filesystem throws rather than silently reporting success on a truncated or failed upload.
Source
Thrown at seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java:389
client.allocate(bufferSize);
// Change to parent directory on the server. Only then can we write to the
// file on the server by opening up an OutputStream. As a side effect the
// working directory on the server is changed to the parent directory of the
// file. The FTP client connection is closed when close() is called on the
// FSDataOutputStream.
client.changeWorkingDirectory(parent.toUri().getPath());
FSDataOutputStream fos =
new FSDataOutputStream(client.storeFileStream(file.getName()), statistics) {
@Override
public void close() throws IOException {
super.close();
if (!client.isConnected()) {
throw new FTPException("Client not connected");
}
boolean cmdCompleted = client.completePendingCommand();
disconnect(client);
if (!cmdCompleted) {
throw new FTPException(
"Could not complete transfer, Reply Code - "
+ client.getReplyCode());
}
}
};
if (!FTPReply.isPositivePreliminary(client.getReplyCode())) {
// The ftpClient is an inconsistent state. Must close the stream
// which in turn will logout and disconnect from FTP server
fos.close();
throw new IOException("Unable to create file: " + file + ", Aborting");
}
return fos;
}
/** This optional operation is not yet supported. */
@Override
public FSDataOutputStream append(Path f, int bufferSize, Progressable progress)
throws IOException {View on GitHub (pinned to cf67b549a7)
Solutions
- Check the FTP server logs and disk space/quota for the target directory
- Verify the FTP user has write permission on the target file path
- Configure passive mode (and correct port range in the firewall) to keep the data channel alive
- Increase connection/idle timeouts and retry the whole write operation
- Check client.getReplyCode() in server logs (e.g. 452/553) to identify the server-side rejection
Example fix
// before
try (FSDataOutputStream out = fs.create(path)) {
out.write(bigBuffer);
}
// after
try (FSDataOutputStream out = fs.create(path)) {
out.write(chunk);
out.flush(); // flush periodically to surface transfer errors early
}
// and retry the entire write on failure instead of assuming partial success Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: check server reachability and target writability
if (!fs.exists(path.getParent())) throw new IllegalStateException("parent dir missing"); Type guard
// Java: no dynamic type guard; guard state instead
boolean safeToWrite(FTPClient client) { return client != null && client.isConnected(); } Try / catch
try (FSDataOutputStream out = fs.create(path)) {
out.write(data);
} catch (IOException e) {
if (e.getMessage().contains("Could not complete transfer")) {
// treat file as corrupt: delete partial file and retry whole write
fs.delete(path, false);
}
throw e;
} Prevention
- Verify FTP server disk space and user quota before large writes
- Enable passive mode and open the data port range in firewalls
- Flush periodically during large uploads to fail fast
- Retry full-file writes, never assume a partially transferred file is valid
When it happens
Trigger: Closing the FSDataOutputStream returned by create() when client.completePendingCommand() returns false — typically caused by the server rejecting or aborting the STOR transfer (disk full, permission denied on target file, connection dropped mid-transfer, server-enforced quota).
Common situations: Uploading to an FTP server whose disk is full or whose user quota is exceeded; network interruption during a large file write; FTP server configured with file size limits; passive-mode/firewall issues that drop the data channel; writing to a directory where the user lacks write permission after the initial file creation handshake succeeded.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Login failed on server - %s, port - %d as user '%s', reply c
- Unable to open file: ${file}, Aborting
- Client not connected
- FTP LIST failed for path=${mask(absolute)}, replyCode=${clie
- Server response ${reply}
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/042fdcae47370c5e.
Report an issue: GitHub.