{"record":{"id":"1e4ded647b0d3fc2","repo":"apache/seatunnel","slug":"ftp-connection-active-mode-test-failed","errorCode":null,"errorMessage":"FTP connection active mode test failed","messagePattern":"FTP connection active mode test failed","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java","lineNumber":220,"sourceCode":"     * @param mode mode\n     */\n    private void setFsFtpConnectionMode(FTPClient client, String mode) throws IOException {\n        FtpConnectionMode connectionMode = FtpConnectionMode.fromMode(mode);\n        switch (connectionMode) {\n            case PASSIVE_LOCAL:\n                client.enterLocalPassiveMode();\n                LOG.info(\"Using passive mode for FTP connection\");\n                break;\n            case ACTIVE_LOCAL:\n                // Create a test directory to check if active mode is working\n                String pathName = \"/.ftptest\" + System.currentTimeMillis();\n                try {\n                    client.enterLocalActiveMode();\n                    // test active mode is working or not\n                    boolean created = client.makeDirectory(pathName);\n                    if (!created) {\n                        LOG.warn(\"Active mode failed, switching to passive mode\");\n                        throw new IOException(\"FTP connection active mode test failed\");\n                    }\n\n                    LOG.info(\"Using active mode for FTP connection\");\n                } catch (IOException e) {\n                    // if active mode failed, switch to passive mode\n                    client.enterLocalPassiveMode();\n                    // update the connection mode to passive mode\n                    getConf()\n                            .set(FS_FTP_CONNECTION_MODE, FtpConnectionMode.PASSIVE_LOCAL.getMode());\n                } finally {\n                    // delete the test directory if it was created\n                    FTPFile[] files = client.listFiles(pathName);\n                    if (files != null && files.length > 0) {\n                        client.deleteFile(pathName);\n                    }\n                }\n                break;\n            default:","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java#L202-L238","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before (config)\nfs.ftp.connection-mode = active_local\n// after (config)\nfs.ftp.connection-mode = passive_local","handlingStrategy":"fallback","validationCode":"// Before running the job, verify active mode works and the user can create dirs:\nFTPClient c = new FTPClient();\nc.connect(host, port);\nif (!c.login(user, pass)) throw new IllegalStateException(\"FTP login failed\");\nc.enterLocalActiveMode();\nString probe = \"/.ftptest-probe\";\nboolean ok = c.makeDirectory(probe);\nif (ok) c.deleteFile(probe);\nboolean activeOk = ok;\nc.logout(); c.disconnect();\nif (!activeOk) System.out.println(\"Set fs.ftp.connection-mode = passive_local\");","typeGuard":null,"tryCatchPattern":"// The connector catches this IOException itself and falls back to passive mode.\n// At job level, treat IOException from connect() as retryable/config-related:\ntry {\n    filesystem.connect();\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"active mode test failed\")) {\n        // switch config to passive_local and retry\n    } else {\n        throw e;\n    }\n}","preventionTips":["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"],"tags":["ftp","network","firewall","fallback"],"backgroundTag":"connection-refused","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}