{"record":{"id":"ad8b65a16c05f912","repo":"pentaho/pentaho-kettle","slug":"failed-to-open-sftp-session","errorCode":null,"errorMessage":"Failed to open SFTP session","messagePattern":"Failed to open SFTP session","errorType":"exception","errorClass":"SftpException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java","lineNumber":488,"sourceCode":"      throw new SshConnectionException( \"Command execution was interrupted\", e );\n    } catch ( Exception e ) {\n      throw new SshConnectionException( \"Failed to execute command: \" + command, e );\n    }\n  }\n\n  @Override\n  public ExecResult exec( String command ) throws SshConnectionException {\n    return exec( command, config.getCommandTimeoutMillis() );\n  }\n\n  @Override\n  public SftpSession openSftp() throws SshConnectionException {\n    try {\n      var factory = SftpClientFactory.instance();\n      var sftp = factory.createSftpClient( session );\n      return new MinaSftpSession( sftp );\n    } catch ( Exception e ) {\n      throw new SftpException( \"Failed to open SFTP session\", e );\n    }\n  }\n\n  /**\n   * Creates an in-memory key provider from key content bytes.\n   * This avoids writing sensitive key data to the filesystem.\n   */\n  private KeyPairProvider createInMemoryKeyProvider( byte[] keyContent ) {\n    return new AbstractKeyPairProvider() {\n      @Override\n      public Iterable<KeyPair> loadKeys( SessionContext session ) throws IOException {\n        try {\n          // Use SecurityUtils to parse the key content directly from input stream\n          ByteArrayInputStream keyStream = new ByteArrayInputStream( keyContent );\n          return SecurityUtils.loadKeyPairIdentities( session, null,\n              keyStream, ( s, r, i ) -> config.getPassphrase() );\n        } catch ( Exception e ) {\n          throw new IOException( \"Failed to parse SSH key content\", e );","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java#L470-L506","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nSftpSession sftp = connection.openSftp();\n// after\nSftpSession sftp;\ntry {\n  if (!connection.isOpen()) connection.open();\n  sftp = connection.openSftp();\n} catch (SftpException e) {\n  throw new KettleException(\"SFTP subsystem unavailable on \" + host + \": \" + e.getCause(), e);\n}","handlingStrategy":"try-catch","validationCode":"if (connection == null || !connection.isOpen()) {\n  connection.open(); // ensure the SSH session is alive before requesting SFTP\n}","typeGuard":null,"tryCatchPattern":"try {\n  SftpSession sftp = connection.openSftp();\n} catch (SftpException e) {\n  logError(\"SFTP open failed: \" + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage()), e);\n  // reconnect session and retry once, or fail the step with actionable message\n}","preventionTips":["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."],"tags":["ssh","sftp","network","connection"],"backgroundTag":"api-request-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}