apache/seatunnel · warning · IOException
FTP connection active mode test failed
Error message
FTP connection active mode test failed
What it means
SeaTunnelFTPFileSystem verifies active FTP mode by issuing a test MKD command (/.ftptest<timestamp>) after switching to local active mode. If the server rejects the mkdir (makeDirectory returns false), it throws this IOException, which is immediately caught: the client falls back to passive mode and the config is rewritten to passive. So the message signals 'active mode unusable, degraded to passive', not a fatal job failure.
Solutions
- Do nothing if passive fallback is acceptable — the connector already switches to passive mode and continues; check logs for 'Using passive mode for FTP connection'.
- Explicitly set fs.ftp.connection-mode = passive_local to skip the active-mode probe and the warning.
- Fix the network path for active mode: open inbound data-port range on the client firewall and configure the FTP server's NAT accordingly.
- Grant the FTP user permission to create directories in the root ('/') so the probe can succeed, or connect with a user whose home is writable.
- Verify the FTP server actually supports MKD (some locked-down servers return 550 for it).
Example fix
// before (config) fs.ftp.connection-mode = active_local // after (config) fs.ftp.connection-mode = passive_local
Defensive patterns
Strategy: fallback
Validate before calling
// Before running the job, verify active mode works and the user can create dirs:
FTPClient c = new FTPClient();
c.connect(host, port);
if (!c.login(user, pass)) throw new IllegalStateException("FTP login failed");
c.enterLocalActiveMode();
String probe = "/.ftptest-probe";
boolean ok = c.makeDirectory(probe);
if (ok) c.deleteFile(probe);
boolean activeOk = ok;
c.logout(); c.disconnect();
if (!activeOk) System.out.println("Set fs.ftp.connection-mode = passive_local"); Try / catch
// The connector catches this IOException itself and falls back to passive mode.
// At job level, treat IOException from connect() as retryable/config-related:
try {
filesystem.connect();
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("active mode test failed")) {
// switch config to passive_local and retry
} else {
throw e;
}
} Prevention
- Set fs.ftp.connection-mode = passive_local unless you specifically need active mode
- Ensure the FTP user has write permission in the root directory (the probe creates /.ftptest<ts>)
- Open inbound data ports on the client firewall if active mode is required
- Test MKD support of the FTP server account before production runs
When it happens
Trigger: fs.ftp.connection-mode is set to active (or defaults to it) and client.makeDirectory('/.ftptest<ts>') returns false during connect() — typically because the server refuses data connections to the client's chosen port, or the user lacks write permission in the root directory to create the test directory.
Common situations: FTP server behind NAT/firewall that blocks inbound data connections to the client's active-mode port; FTP user without write permission on '/'; server disallowing MKD; misconfigured active mode when the client host is not publicly reachable.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Client not connected
- Could not complete transfer, Reply Code
- FTP LIST failed for path=
- Login failed on server
- Server response
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/1e4ded647b0d3fc2.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java:220
* @param mode mode
*/
private void setFsFtpConnectionMode(FTPClient client, String mode) throws IOException {
FtpConnectionMode connectionMode = FtpConnectionMode.fromMode(mode);
switch (connectionMode) {
case PASSIVE_LOCAL:
client.enterLocalPassiveMode();
LOG.info("Using passive mode for FTP connection");
break;
case ACTIVE_LOCAL:
// Create a test directory to check if active mode is working
String pathName = "/.ftptest" + System.currentTimeMillis();
try {
client.enterLocalActiveMode();
// test active mode is working or not
boolean created = client.makeDirectory(pathName);
if (!created) {
LOG.warn("Active mode failed, switching to passive mode");
throw new IOException("FTP connection active mode test failed");
}
LOG.info("Using active mode for FTP connection");
} catch (IOException e) {
// if active mode failed, switch to passive mode
client.enterLocalPassiveMode();
// update the connection mode to passive mode
getConf()
.set(FS_FTP_CONNECTION_MODE, FtpConnectionMode.PASSIVE_LOCAL.getMode());
} finally {
// delete the test directory if it was created
FTPFile[] files = client.listFiles(pathName);
if (files != null && files.length > 0) {
client.deleteFile(pathName);
}
}
break;
default:View on GitHub (pinned to cf67b549a7)