{"record":{"id":"9aaf1d765d59911e","repo":"apache/seatunnel","slug":"server-response-reply","errorCode":null,"errorMessage":"Server response ${reply}","messagePattern":"Server response (.+?)","errorType":"exception","errorClass":"java.net.ConnectException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java","lineNumber":165,"sourceCode":"\n        // Check if remote verification is enabled\n        boolean remoteVerificationEnabled =\n                conf.getBoolean(\n                        FS_FTP_REMOTE_VERIFICATION_ENABLED,\n                        FtpFileBaseOptions.FTP_REMOTE_VERIFICATION_ENABLED.defaultValue());\n        client.setRemoteVerificationEnabled(remoteVerificationEnabled);\n\n        // Retrieve host, port, user, and password from configuration\n        String host = conf.get(FS_FTP_HOST);\n        int port = conf.getInt(FS_FTP_HOST_PORT, FTP.DEFAULT_PORT);\n        String user = conf.get(FS_FTP_USER_PREFIX + host);\n        String password = conf.get(FS_FTP_PASSWORD_PREFIX + host);\n\n        // Connect to the FTP server\n        client.connect(host, port);\n        int reply = client.getReplyCode();\n        if (!FTPReply.isPositiveCompletion(reply)) {\n            throw NetUtils.wrapException(\n                    host,\n                    port,\n                    NetUtils.UNKNOWN_HOST,\n                    0,\n                    new ConnectException(\"Server response \" + reply));\n        }\n\n        // Log in to the FTP server\n        if (!client.login(user, password)) {\n            throw new IOException(\n                    String.format(\n                            \"Login failed on server - %s, port - %d as user '%s', reply code: %d\",\n                            host, port, user, client.getReplyCode()));\n        }\n\n        // Set the file type to binary and buffer size\n        client.setFileType(FTP.BINARY_FILE_TYPE);\n        client.setBufferSize(DEFAULT_BUFFER_SIZE);","sourceCodeStart":147,"sourceCodeEnd":183,"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#L147-L183","documentation":"The FTP file system's connect() opened a TCP socket to the configured host:port, but the server's first reply code was not a positive completion (not 1xx/2xx/3xx per FTPReply.isPositiveCompletion). The connector wraps the raw reply code in a ConnectException via NetUtils.wrapException, so the message looks like 'Server response 421' (or 530, 500, etc.). The socket connected, but the FTP service refused to proceed — e.g. server overloaded, TLS required, or the port is not actually an FTP endpoint.","triggerScenarios":"SeaTunnelFTPFileSystem.connect() — triggered on client(), openFileStatusListingSession(), getHomeDirectory() — when client.connect(host, port) succeeds at TCP level but client.getReplyCode() returns a non-positive-completion code: 421 (service not available / too many connections), 530 (not logged in / TLS required before commands), 500/502 (not an FTP server on that port), 120 (service ready in N minutes).","commonSituations":"Connecting to an FTPS-only server that requires AUTH TLS before serving commands; hitting a max-connections limit (421); pointing fs.ftp.host at the wrong port or at an SFTP/HTTP service (500); firewall/proxy allowing TCP connect but the FTP daemon rejecting; server under load during peak hours.","solutions":["Read the reply code in the message: 421 = server busy/max connections (retry later or raise server connection limit); 530/needs-TLS = switch to an FTPS-capable setup or enable TLS; 500/502 = you are not talking to an FTP server (check host/port).","Verify the host and port config (fs.ftp.host, fs.ftp.host-port) point at a plain FTP (or explicit-FTPS) endpoint — test with 'ftp host port' or a client like FileZilla and compare the banner.","If the server requires FTPS, this SeaTunnelFTPFileSystem uses commons-net FTPClient without TLS — use an FTP server that allows plain FTP, or front it with a plain-FTP proxy/stunnel.","Check server-side limits and health (max clients, IP allowlist, fail2ban) and retry with backoff on transient 421 codes.","Confirm firewall/security-group rules permit the data-channel ports too, since some servers reject control sessions when the data channel cannot be established."],"exampleFix":"// before: wrong port (SFTP server) -> Server response 500\nString host = \"sftp.example.com\";\nconf.set(FS_FTP_HOST, host);\nconf.setInt(FS_FTP_HOST_PORT, 22); // SFTP, not FTP\n\n// after: point at the real FTP service port\nconf.set(FS_FTP_HOST, \"ftp.example.com\");\nconf.setInt(FS_FTP_HOST_PORT, 21); // standard FTP control port","handlingStrategy":"retry","validationCode":"// Validate reachability and banner before submitting the job\ntry (Socket s = new Socket()) {\n    s.connect(new InetSocketAddress(host, port), 5000);\n    BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));\n    String banner = in.readLine(); // e.g. \"220 ftp.example.com FTP server ready\"\n    if (banner == null || !banner.startsWith(\"220\")) {\n        throw new IllegalStateException(\"Endpoint does not look like a healthy FTP server: \" + banner);\n    }\n} catch (java.net.UnknownHostException | java.net.SocketTimeoutException e) {\n    throw new IllegalStateException(\"Cannot reach FTP host/port: \" + host + \":\" + port, e);\n}","typeGuard":null,"tryCatchPattern":"int attempts = 0;\nwhile (true) {\n    try {\n        ftpFileSystem.list(...); // triggers connect()\n        break;\n    } catch (IOException e) {\n        Matcher m = Pattern.compile(\"Server response (\\\\d+)\").matcher(e.getMessage());\n        if (m.find()) {\n            int reply = Integer.parseInt(m.group(1));\n            if (reply == 421 && ++attempts <= 3) { // transient: server busy\n                Thread.sleep(2000L * attempts);\n                continue;\n            }\n        }\n        throw e; // 530/500 etc. are configuration errors, do not retry\n    }\n}","preventionTips":["Confirm the endpoint serves plain FTP (banner test with nc/ftp) — not SFTP or FTPS-only — before wiring the connector.","Check server-side max-client limits and monitor 421 codes under load; raise limits or add retry with backoff.","Verify host/port config against the actual FTP daemon (default control port 21).","Ensure firewalls allow both the control connection and passive/active data-channel ports.","If the server mandates TLS (530 before AUTH TLS), use an FTP server allowing plain FTP or a plain-FTP proxy, since this client does not do FTPS."],"tags":["ftp","network","connection","reply-code"],"backgroundTag":"ftp-connection-rejected","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}