apache/hadoop · warning · FTPException
Failed to disconnect
Error message
Failed to disconnect
What it means
getHomeDirectory() disconnects its short-lived client inside a finally block; any IOException from disconnect() is wrapped as FTPException("Failed to disconnect"). Because it is thrown from finally, it replaces both the computed home directory and any primary "Failed to get home directory" exception — the cleanup failure masks what actually happened.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/ftp/FTPFileSystem.java:726
public Path getWorkingDirectory() {
// Return home directory always since we do not maintain state.
return getHomeDirectory();
}
@Override
public Path getHomeDirectory() {
FTPClient client = null;
try {
client = connect();
Path homeDir = new Path(client.printWorkingDirectory());
return homeDir;
} catch (IOException ioe) {
throw new FTPException("Failed to get home directory", ioe);
} finally {
try {
disconnect(client);
} catch (IOException ioe) {
throw new FTPException("Failed to disconnect", ioe);
}
}
}
@Override
public void setWorkingDirectory(Path newDir) {
// we do not maintain the working directory state
}
}
View on GitHub (pinned to 2add963021)
Solutions
- Look at the cause chain first: if a "Failed to get home directory" cause is attached, fix that — the disconnect error is secondary noise
- Treat the disconnect failure as non-fatal when you can recompute the value: catch, log, and continue with a retry
- Cache/reuse the FileSystem instance instead of triggering per-call connections; fewer connect/disconnect cycles means fewer close failures
- Align client keepalive with server-side idle limits (e.g. vsftpd idle_session_timeout) so sessions survive until QUIT
Example fix
// before
Path home = fs.getHomeDirectory(); // may throw FTPException("Failed to disconnect"), masking the real error
// after
Path home;
try {
home = fs.getHomeDirectory();
} catch (FTPException e) {
LOG.warn("getHomeDirectory failed; cause chain tells whether it was connect or disconnect: {}", e.getCause(), e);
throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
wrap getHomeDirectory()/getWorkingDirectory() calls; on FTPException inspect the cause chain — if the failure is only the disconnect (connect and PWD succeeded per logs), log and retry the call instead of propagating the masked cleanup error.
Prevention
- Cache the home directory instead of calling getHomeDirectory() repeatedly
- Reuse FileSystem instances to avoid per-call connect/disconnect cycles
- Align client keepalive with the server's idle timeout so sessions survive until QUIT
When it happens
Trigger: The server closes the control connection before the client can send QUIT (idle timeout, aggressive firewall); the socket is reset during logout; or the initial connect/PWD already failed and the disconnect of the half-open client also fails.
Common situations: Servers with very short idle timeouts killing sessions between operations; NAT dropping connection state; per-call connect/disconnect patterns (getWorkingDirectory() is invoked liberally by higher-level code) multiplying exposure to close-time failures.
Related errors
- File check failed
- Source path {src} does not exist
- Destination path {dst} already exists
- Cannot rename {absoluteSrc} under itself : {absoluteDst}
- Cannot rename source: {absoluteSrc} to {absoluteDst} -only s
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/c1507e0aa10fb092.
Report an issue: GitHub.