apache/seatunnel · error · FileNotFoundException
File ${file} does not exist.
Error message
File ${file} does not exist. What it means
Thrown by SeaTunnelFTPFileSystem.getFileStatus() as a FileNotFoundException: the parent directory listing succeeded, but no entry in it matched the requested file name, so the file is confirmed absent on the FTP server.
Source
Thrown at seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java:665
boolean isDir = true;
int blockReplication = 1;
long blockSize = DEFAULT_BLOCK_SIZE; // Block Size not known.
long modTime = -1; // Modification time of root dir not known.
Path root = new Path("/");
return new FileStatus(
length, isDir, blockReplication, blockSize, modTime, root.makeQualified(this));
}
String pathName = parentPath.toUri().getPath();
FTPFile[] ftpFiles = client.listFiles(pathName);
if (ftpFiles != null) {
for (FTPFile ftpFile : ftpFiles) {
if (ftpFile.getName().equals(file.getName())) { // file found in dir
fileStat = getFileStatus(ftpFile, parentPath);
break;
}
}
if (fileStat == null) {
throw new FileNotFoundException("File " + file + " does not exist.");
}
} else {
throw new FileNotFoundException("File " + file + " does not exist.");
}
return fileStat;
}
/**
* Convert the file information in FTPFile to a {@link FileStatus} object. *
*
* @param ftpFile ftpFile
* @param parentPath parent path
* @return FileStatus
*/
private FileStatus getFileStatus(FTPFile ftpFile, Path parentPath) {
long length = ftpFile.getSize();
boolean isDir = ftpFile.isDirectory();
int blockReplication = 1;View on GitHub (pinned to cf67b549a7)
Solutions
- List the parent directory and compare actual file names with the requested path
- Check file name case matches the server exactly
- Fix the upstream step or file-naming pattern that produces the file
- Add an exists() guard or catch FileNotFoundException to handle absence gracefully
Example fix
// before
FileStatus st = fs.getFileStatus(new Path("/data/report_2026-13-01.csv"));
// after
Path p = new Path("/data/report_2026-09-01.csv"); // corrected pattern
if (fs.exists(p)) {
FileStatus st = fs.getFileStatus(p);
} Defensive patterns
Strategy: try-catch
Validate before calling
Path p = new Path("/data/report.csv");
if (!fs.exists(p)) {
throw new IllegalStateException("Expected input file missing: " + p);
} Try / catch
try {
FileStatus st = fs.getFileStatus(p);
} catch (FileNotFoundException e) {
// file genuinely absent: handle as missing input / trigger upstream job
} Prevention
- Confirm upstream steps completed and wrote the expected file names
- Match file name case exactly against server listings
- Avoid fragile date/time templated names without validating the rendered value
- Treat file absence as a first-class state (exists() checks, not exceptions)
When it happens
Trigger: Calling getFileStatus()/exists-resolution paths with a file name that does not appear in the parent directory listing — file deleted before the call, wrong file name/case, or stale name generated by upstream logic.
Common situations: SeaTunnel job expecting an input file produced by a previous step that failed or wrote a different name; case mismatch (data.CSV vs data.csv); race with another job deleting the file; templated filenames with wrong date/time placeholders.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Path ${file} is a directory.
- FTP directory does not exist: ${mask(absolute)}
- Source path %s does not exist
- AmazonDocumentDB TLS CA bundle is not a readable file:
- clickhouse local file not exists
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/1737a1defe096f54.
Report an issue: GitHub.