pentaho/pentaho-kettle · critical · SshConnectionException

SSH connection failed -

Error message

SSH connection failed - 

What it means

MinaSshConnection.createConnection() catches any Exception during SSH session establishment and rethrows it as SshConnectionException with message built from buildConnectionErrorMessage(e). It is the generic connect-failure path; the specific reason (refused, auth, key, timeout) is in the cause and the enriched message.

Solutions

  1. Read the full message/cause to get the concrete failure (refused vs auth vs algorithm negotiation)
  2. Test basic reachability: ping/telnet to host:port from the same machine
  3. Verify username/password or key file and passphrase are correct and the key format is supported (OpenSSH/PEM)
  4. If the server only offers legacy algorithms, enable them in the SSH client or update the server; upgrade the MINA SSHD library if negotiation fails
  5. Check proxy configuration if isProxyConfigured() is true, since the proxy path is exercised instead of the direct one

Example fix

// before
SshConnection conn = new MinaSshConnection(config);
conn.connect(); // opaque failure
// after
try {
  conn.connect();
} catch (SshConnectionException e) {
  log.error("SSH connect to {}:{} failed: {}", config.getHost(), config.getPort(), e.getMessage(), e.getCause());
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight before connect()
if (config.getHost() == null || config.getHost().isBlank()) throw new IllegalArgumentException("host required");
if (config.getPort() <= 0) throw new IllegalArgumentException("port required");
try (Socket s = new Socket()) { s.connect(new InetSocketAddress(config.getHost(), config.getPort()), 5000); }
catch (IOException e) { throw new IllegalStateException("host:port unreachable before SSH attempt", e); }

Type guard

boolean reachable(String host, int port) {
  try (Socket s = new Socket()) { s.connect(new InetSocketAddress(host, port), 5000); return true; }
  catch (IOException e) { return false; }
}

Try / catch

try {
  conn.connect();
} catch (SshConnectionException e) {
  Throwable root = e;
  while (root.getCause() != null) root = root.getCause();
  log.error("SSH connect failed (root cause: {}): {}", root.getClass().getSimpleName(), root.getMessage());
  throw e;
}

Prevention

When it happens

Trigger: Calling connect() when the host is unreachable/port closed, credentials or key auth rejected, no supported key exchange/cipher negotiated, or the proxy path throws an unexpected exception type.

Common situations: Wrong host/port in the SSH connection metadata, SSH server firewalling the client, unsupported or passphrase-protected private key without a supplied passphrase, server disabled the auth method the client tries, or MINA SSHD version incompatibility with the server's algorithms.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/cf14ab95170dcb56. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java:135

    client = SshClient.setUpDefaultClient();

    // Disable strict host key checking to avoid key exchange issues
    client.setServerKeyVerifier( ( clientSession, remoteAddress, serverKey ) -> true );

    client.start();
  }

  private ConnectFuture createConnection() throws SshConnectionException {
    try {
      if ( isProxyConfigured() ) {
        return createProxyConnection();
      } else {
        return createDirectConnection();
      }
    } catch ( SshConnectionException e ) {
      throw e; // Re-throw SshConnectionException as-is
    } catch ( Exception e ) {
      throw new SshConnectionException( buildConnectionErrorMessage( e ), e );
    }
  }

  private boolean isProxyConfigured() {
    return config.getProxyHost() != null && !config.getProxyHost().trim().isEmpty();
  }

  private ConnectFuture createDirectConnection() throws IOException {
    log( DEBUG, "SSH Direct Connection: " + config.getHost() + ":" + config.getPort()
        + formatUserInfo() );
    return client.connect( config.getUsername(), config.getHost(), config.getPort() );
  }

  private ConnectFuture createProxyConnection() throws SshConnectionException, IOException {
    log( BASIC, "SSH over HTTP Proxy: " + config.getProxyHost() + ":" + config.getProxyPort()
        + " -> " + config.getHost() + ":" + config.getPort() );
    log( DEBUG, "HTTP Proxy Details - Target User: " + config.getUsername() + ", Auth: " + config.getAuthType() );

View on GitHub (pinned to f3058517a1)