pentaho/pentaho-kettle · error · SftpException
Failed to open SFTP session
Error message
Failed to open SFTP session
What it means
MinaSshConnection.openSftp() wraps any exception raised while creating an SFTP subsystem channel on top of an established Apache MINA SSHD session into a SftpException with this message. The SSH transport session already succeeded; the failure is specifically in opening the SFTP client/subsystem on that session. The original cause (server refusing the sftp subsystem, timeout, channel closed) is attached as the cause.
Solutions
- Inspect the wrapped cause with e.getCause() to see the real failure from MINA SSHD.
- Verify the SSH server has the sftp subsystem enabled (Subsystem sftp internal-sftp or sftp-server binary path in sshd_config).
- Reopen/refresh the SSH session if it was closed or timed out before calling openSftp.
- Confirm the authenticated user is permitted to use SFTP (not shell-only or chroot-restricted incorrectly).
Example fix
// before
SftpSession sftp = connection.openSftp();
// after
SftpSession sftp;
try {
if (!connection.isOpen()) connection.open();
sftp = connection.openSftp();
} catch (SftpException e) {
throw new KettleException("SFTP subsystem unavailable on " + host + ": " + e.getCause(), e);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (connection == null || !connection.isOpen()) {
connection.open(); // ensure the SSH session is alive before requesting SFTP
} Try / catch
try {
SftpSession sftp = connection.openSftp();
} catch (SftpException e) {
logError("SFTP open failed: " + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()), e);
// reconnect session and retry once, or fail the step with actionable message
} Prevention
- Confirm the target server has the sftp subsystem enabled before using SFTP-based steps.
- Keep-alive / heartbeat the SSH session to avoid idle disconnects.
- Always log e.getCause() — the SftpException message alone hides the real cause.
When it happens
Trigger: Calling SftpClientFactory.instance().createSftpClient(session) fails: the server does not support or denies the 'sftp' subsystem, the session has been closed/disconnected before the call, or an I/O error occurs while opening the channel.
Common situations: SSH server (e.g. hardened OpenSSH with Subsystem sftp disabled or restricted via ChrootDirectory/ForceCommand internal-sftp) refuses the subsystem; connection idle-timed out and the session is dead; firewall drops the channel; user lacks permission for SFTP access.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- Failed to download file:
- Max connection attempts reached
- SFTPPUT.Error.Connection
- SSH connection failed -
- SSH connection failed during await
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/ad8b65a16c05f912.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java:488
throw new SshConnectionException( "Command execution was interrupted", e );
} catch ( Exception e ) {
throw new SshConnectionException( "Failed to execute command: " + command, e );
}
}
@Override
public ExecResult exec( String command ) throws SshConnectionException {
return exec( command, config.getCommandTimeoutMillis() );
}
@Override
public SftpSession openSftp() throws SshConnectionException {
try {
var factory = SftpClientFactory.instance();
var sftp = factory.createSftpClient( session );
return new MinaSftpSession( sftp );
} catch ( Exception e ) {
throw new SftpException( "Failed to open SFTP session", e );
}
}
/**
* Creates an in-memory key provider from key content bytes.
* This avoids writing sensitive key data to the filesystem.
*/
private KeyPairProvider createInMemoryKeyProvider( byte[] keyContent ) {
return new AbstractKeyPairProvider() {
@Override
public Iterable<KeyPair> loadKeys( SessionContext session ) throws IOException {
try {
// Use SecurityUtils to parse the key content directly from input stream
ByteArrayInputStream keyStream = new ByteArrayInputStream( keyContent );
return SecurityUtils.loadKeyPairIdentities( session, null,
keyStream, ( s, r, i ) -> config.getPassphrase() );
} catch ( Exception e ) {
throw new IOException( "Failed to parse SSH key content", e );View on GitHub (pinned to f3058517a1)