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
- Inspect the logged count and directory, then list that directory manually (ftp/ls) to identify the unparseable entries (symlinks, special files, odd encodings).
- Prefer MLSD over LIST if the server supports it, or configure the FTP client's parser so listing lines are parsed correctly.
- Rename or remove problem entries (special files, files with broken encodings) on the FTP server.
- 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
- Avoid special files, symlinks, or non-regular entries on FTP paths consumed by the job
- Use consistent filename encodings (UTF-8) on the FTP server
- Verify the server's LIST output parses correctly with a manual session before production
- Re-check important paths with getFileStatus if a listing warning names that directory
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
- Can't make directory for path
- Cannot get split ' ' to get databaseName and tableName
- Cannot rename under itself
- Client not connected
- Could not complete transfer, Reply Code
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)