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

  1. 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'.
  2. Explicitly set fs.ftp.connection-mode = passive_local to skip the active-mode probe and the warning.
  3. Fix the network path for active mode: open inbound data-port range on the client firewall and configure the FTP server's NAT accordingly.
  4. 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.
  5. 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

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


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)