apache/seatunnel · warning · IOException

StringUtils.stringifyException(sessionLookupFailure)

Error message

StringUtils.stringifyException(sessionLookupFailure)

What it means

closeChannel disconnects a channel and its SSH session; if retrieving the channel's session (channel.getSession()) itself throws JSchException, the exception is remembered and rethrown as an IOException containing the full trace from StringUtils.stringifyException. It prevents silently leaking an orphaned SSH session when teardown cannot discover the session.

Solutions

  1. Inspect the embedded stack trace for the underlying JSch cause; if it is benign (already disconnected), ensure close paths avoid double-close (idempotent cleanup)
  2. Upgrade/patch the connector so sessionLookupFailure is only fatal for unexpected states
  3. Treat as a warning-level leak risk: ensure the pool's shutdown eventually cleans sessions; recycle the filesystem afterwards

Example fix

// before
channel.disconnect(); // stale channel later fails getSession()
pool.closeChannel(channel, null);
// after
if (channel.isConnected()) { channel.disconnect(); }
// handle stale channels idempotently
Defensive patterns

Strategy: try-catch

Try / catch

try {
    poolOp();
} catch (IOException e) {
    if (e.getMessage().contains("com.jcraft.jsch.JSchException")) {
        LOG.warn("SFTP cleanup hit stale channel; recycling filesystem", e);
        recycleFileSystem();
    } else throw e;
}

Prevention

When it happens

Trigger: closeChannel(channel, ...) is invoked (from registerConnection failure, shutdown, connect error handling, or disconnect) while the channel is in a state where getSession() fails — e.g. channel already fully disconnected/closed by the remote side.

Common situations: Server dropped the connection and the channel object is stale; double-close paths calling closeChannel twice; abrupt network loss making session lookup fail during cleanup.

Related errors


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

Appendix: source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPConnectionPool.java:289

    }

    /**
     * Close both connection resources, preferring the session captured before the channel can lose
     * its back-link during cancellation.
     */
    private void closeChannel(ChannelSftp channel, Session capturedSession) throws IOException {
        JSchException sessionLookupFailure = null;
        Session session = capturedSession;
        if (session == null) {
            try {
                session = channel.getSession();
            } catch (JSchException e) {
                sessionLookupFailure = e;
            }
        }
        closeConnectionResources(channel, session);
        if (sessionLookupFailure != null) {
            throw new IOException(StringUtils.stringifyException(sessionLookupFailure));
        }
    }

    /** Disconnect the SFTP channel and its SSH session when either has already been created. */
    private void closeConnectionResources(ChannelSftp channel, Session session) {
        if (channel != null && channel.isConnected()) {
            channel.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }

    public int getIdleCount() {
        return this.idleConnections == null ? 0 : this.idleConnections.size();
    }

    public int getLiveConnCount() {

View on GitHub (pinned to cf67b549a7)