apache/seatunnel · error · IOException

StringUtils.stringifyException(e)

Error message

StringUtils.stringifyException(e)

What it means

registerConnection wraps JSchException raised while registering a newly opened SFTP channel/session into the pool, converting it to an IOException whose message is the full stack trace produced by StringUtils.stringifyException(e). It indicates the SSH layer failed (auth, session state, transport) during pool registration.

Solutions

  1. Read the embedded stack trace (the message IS the trace) to find the underlying JSch failure and fix that root cause
  2. Verify SFTP host/port/credentials and host-key configuration
  3. Check server MaxSessions/MaxStartups limits (sshd_config) and connection count against the pool's maxConnection
  4. Add retry with backoff around filesystem initialization for transient SSH failures
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight connectivity check before initializing the pool
new JSch().getSession(user, host, port).connect(timeout);

Try / catch

try {
    fs.initialize(uri, conf);
} catch (IOException e) {
    if (e.getMessage().contains("com.jcraft.jsch.JSchException")) retryWithBackoff();
    else throw e;
}

Prevention

When it happens

Trigger: channel.connect()/session handshake succeeded enough to open the channel, but the second registerConnection(channel, channel.getSession(), info) path throws JSchException — e.g. session dropped between connect and registration, or the channel cannot provide its session.

Common situations: Flaky SSH network, server-side session limits reached, wrong host key/auth config causing intermittent JSch failures, firewall dropping the connection mid-handshake.

Related errors


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

        if (info == null) {
            return false;
        }
        HashSet<ChannelSftp> cons = idleConnections.get(info);
        if (cons == null) {
            cons = new HashSet<ChannelSftp>();
            idleConnections.put(info, cons);
        }
        cons.add(channel);
        return true;
    }

    /** Register a newly opened connection unless shutdown won the race. */
    boolean registerConnection(ChannelSftp channel, ConnectionInfo info) throws IOException {
        try {
            return registerConnection(channel, channel.getSession(), info);
        } catch (JSchException e) {
            closeChannel(channel, null);
            throw new IOException(StringUtils.stringifyException(e));
        }
    }

    /** Register the channel together with the session captured when the connection was opened. */
    private boolean registerConnection(ChannelSftp channel, Session session, ConnectionInfo info)
            throws IOException {
        synchronized (this) {
            if (con2infoMap != null) {
                con2infoMap.put(channel, info);
                con2sessionMap.put(channel, session);
                liveConnectionCount++;
                return true;
            }
        }
        closeChannel(channel, session);
        return false;
    }

View on GitHub (pinned to cf67b549a7)