apache/seatunnel · warning

Skipped unparseable FTP listing entries under

Error message

Skipped ${skipped} unparseable FTP listing entries under ${mask(absolute)}

What it means

While paginating a recursive FTP listing, list() calls emitFileStatuses for each page of FTPFile entries; entries that cannot be parsed into SeaTunnel FileStatus objects (malformed raw listing lines, nulls, unsupported types) are skipped and counted. When any were skipped, this warning names how many and under which (masked) directory. The listing continues with the parseable entries; it is informational, not fatal.

Solutions

  1. Inspect the logged count and directory, then list that directory manually (ftp/ls) to identify the unparseable entries (symlinks, special files, odd encodings).
  2. Prefer MLSD over LIST if the server supports it, or configure the FTP client's parser so listing lines are parsed correctly.
  3. Rename or remove problem entries (special files, files with broken encodings) on the FTP server.
  4. If the skipped files are not needed for the job, treat this as expected noise; otherwise confirm required files appear among the emitted statuses.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: probe the directory listing yourself before the job and inspect raw entries
FTPClient c = /* connected client */;
FTPFile[] files = c.listFiles(path);
for (FTPFile f : files) {
    if (f == null || f.getName() == null || f.getType() == FTPFile.UNKNOWN_TYPE) {
        System.out.println("Unparseable entry under " + path);
    }
}

Try / catch

// Skipped entries are only warned; guard downstream consumers against missing paths:
try {
    FileStatus status = filesystem.getFileStatus(new Path(target));
} catch (IOException e) {
    // file may have been one of the skipped/unparseable entries
    LOG.warn("Target not listed by FTP: " + target, e);
}

Prevention

When it happens

Trigger: During list(), a page from the FTPListingEngine (engine.getNext(PAGE_SIZE)) contains FTPFile entries that emitFileStatuses cannot map — e.g. FTPFile with null/invalid name, unknown or raw type, or entries the server's LIST output produced that the parser could not normalize.

Common situations: Non-standard FTP server LIST formats (unusual MLSD/LIST output the commons-net parser mangles); symbolic links or special files (devices, sockets) on the FTP server; filenames with exotic encodings or embedded newlines; permission-locked directories returning degenerate entries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/07785864fa124bee. 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:548

            String previousDirectory = client.printWorkingDirectory();
            if (!client.changeWorkingDirectory(absolute.toUri().getPath())) {
                throw new FileNotFoundException("FTP directory does not exist: " + mask(absolute));
            }
            Throwable failure = null;
            try {
                FTPListParseEngine engine = client.initiateListParsing();
                if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
                    throw new IOException(
                            "FTP LIST failed for path="
                                    + mask(absolute)
                                    + ", replyCode="
                                    + client.getReplyCode());
                }
                while (engine.hasNext()) {
                    FTPFile[] files = engine.getNext(PAGE_SIZE);
                    int skipped = emitFileStatuses(files, absolute, consumer);
                    if (skipped > 0) {
                        LOG.warn(
                                "Skipped "
                                        + skipped
                                        + " unparseable FTP listing entries under "
                                        + mask(absolute));
                    }
                }
            } catch (IOException | RuntimeException | Error e) {
                failure = e;
                throw e;
            } finally {
                if (!client.changeWorkingDirectory(previousDirectory)) {
                    IOException restoreFailure =
                            new IOException(
                                    "Failed to restore FTP working directory, replyCode="
                                            + client.getReplyCode());
                    if (failure != null) {
                        failure.addSuppressed(restoreFailure);
                    } else {

View on GitHub (pinned to cf67b549a7)