apache/seatunnel · error · IOException

Unable to open file: ${file}, Aborting

Error message

Unable to open file: ${file}, Aborting

What it means

SeaTunnelFTPFileSystem.open() issues RETR via client.retrieveFileStream(); the FSDataInputStream is constructed first, but if the server's reply code is not a positive preliminary (1xx) response, the client is in an inconsistent state. The stream is closed (logging out/disconnecting) and IOException('Unable to open file: <file>, Aborting') is thrown.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-ftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/ftp/system/SeaTunnelFTPFileSystem.java:328

            throw new FileNotFoundException("Path " + file + " is a directory.");
        }
        client.allocate(bufferSize);
        Path parent = absolute.getParent();
        // Change to parent directory on the
        // server. Only then can we read the
        // file
        // on the server by opening up an InputStream. As a side effect the working
        // directory on the server is changed to the parent directory of the file.
        // The FTP client connection is closed when close() is called on the
        // FSDataInputStream.
        client.changeWorkingDirectory(parent.toUri().getPath());
        InputStream is = client.retrieveFileStream(file.getName());
        FSDataInputStream fis = new FSDataInputStream(new FTPInputStream(is, client, statistics));
        if (!FTPReply.isPositivePreliminary(client.getReplyCode())) {
            // The ftpClient is an inconsistent state. Must close the stream
            // which in turn will logout and disconnect from FTP server
            fis.close();
            throw new IOException("Unable to open file: " + file + ", Aborting");
        }
        return fis;
    }

    /**
     * A stream obtained via this call must be closed before using other APIs of this class or else
     * the invocation will block.
     */
    @Override
    public FSDataOutputStream create(
            Path file,
            FsPermission permission,
            boolean overwrite,
            int bufferSize,
            short replication,
            long blockSize,
            Progressable progress)
            throws IOException {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Check FTP server logs for the RETR reply code to see why the transfer was refused
  2. Toggle ftp.connection.mode between active and passive to work through the firewall/NAT
  3. Verify the FTP user has read permission on the file and execute permission on parent directories
  4. Confirm the file still exists at open time (it may have been deleted or renamed between listing and read)

Example fix

// before
"ftp.connection.mode" = "active" // corporate NAT blocks the active data connection
// after
"ftp.connection.mode" = "passive"
Defensive patterns

Strategy: try-catch

Validate before calling

// Preflight RETR check via a plain FTP client
FTPClient c = connect();
boolean ok = c.retrieveFile(file.getName(), NullOutputStream.INSTANCE);
int reply = c.getReplyCode();
disconnect(c);
if (!ok) throw new IllegalStateException("FTP server refuses RETR for " + file.getName() + ", reply=" + reply);

Try / catch

try {
    return fs.open(path);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().contains("Unable to open file")) {
        LOG.warn("RETR failed for {} (reply non-1xx); check perms/firewall/mode", path, e);
        // retry with alternate ftp.connection.mode
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling open(file) when the FTP server answers RETR with a non-1xx reply: file not retrievable (permissions, not found at the server side due to changed working directory), server refuses transfer, or data connection cannot be established (firewall blocking passive/active mode).

Common situations: File removed between listing and open; FTP user lacks read permission; firewall/NAT breaks the data channel (common fix: switch ftp.connection.mode between active/passive); server-side transfer restrictions (e.g. TLS required).

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/151d0f3f82d49135. Report an issue: GitHub.