{"record":{"id":"120e41382ede1eb5","repo":"pentaho/pentaho-kettle","slug":"failed-to-parse-ssh-key-content","errorCode":null,"errorMessage":"Failed to parse SSH key content","messagePattern":"Failed to parse SSH key content","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java","lineNumber":506,"sourceCode":"      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 );\n        }\n      }\n    };\n  }\n\n  @Override\n  public void close() {\n    if ( session != null ) {\n      session.close( false );\n    }\n    if ( client != null ) {\n      client.stop();\n    }\n  }\n}\n","sourceCodeStart":488,"sourceCodeEnd":522,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java#L488-L522","documentation":"In MinaSshConnection.loadKeys(), the key-pair provider parses raw key content bytes via SecurityUtils.loadKeyPairIdentities(). If parsing fails for any reason (malformed key, unsupported algorithm, wrong PEM/openssh format, unreadable stream), it is rethrown as IOException with this message. It signals the supplied SSH private key bytes could not be turned into a KeyPair.","triggerScenarios":"loadKeyPairIdentities receives keyContent bytes that are not a parseable private key: truncated/pasted key, wrong passphrase supplier, unsupported key format (e.g. PuTTY .ppk), or encrypted key with missing/incorrect passphrase.","commonSituations":"User pasted a PuTTY PPK or public key instead of a private OpenSSH key; key copied without the BEGIN/END lines; passphrase changed but configuration still has the old one; key generated with an algorithm (e.g. sk-ssh-ed25519) unsupported by the bundled MINA SSHD version.","solutions":["Verify the key content is a complete private key (-----BEGIN OPENSSH/rsa PRIVATE KEY----- through matching END line, newlines intact).","Provide the correct passphrase via config.getPassphrase() for encrypted keys.","Convert unsupported formats: puttygen → OpenSSH format; regenerate keys with supported algorithms (RSA, ECDSA, ed25519).","Check the wrapped cause for the exact parse failure and confirm the MINA SSHD version supports the key's algorithm."],"exampleFix":"// before\nString key = prefs.getSshKey(); // possibly a .ppk file\nconnection.setKeyContent(key.getBytes());\n// after\nif (!key.startsWith(\"-----BEGIN\")) {\n  throw new KettleException(\"SSH key must be OpenSSH private key format, not PPK or public key\");\n}\nconnection.setKeyContent(key.getBytes(StandardCharsets.UTF_8));","handlingStrategy":"validation","validationCode":"String key = config.getSshKeyContent();\nif (key == null || !key.startsWith(\"-----BEGIN\")) {\n  throw new IllegalArgumentException(\"SSH private key must be in OpenSSH PEM format\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  connection.setKeyContent(keyBytes);\n} catch (IOException e) {\n  throw new KettleException(\"Invalid SSH key: \" + e.getCause().getMessage(), e);\n}","preventionTips":["Store keys in OpenSSH PEM format only; convert PuTTY .ppk files with puttygen beforehand.","Never paste public keys where private keys are expected — validate the BEGIN line.","Keep passphrase configuration in sync with key encryption.","Trim/preserve newlines when copying keys from secret managers."],"tags":["ssh","key-parsing","authentication","configuration"],"backgroundTag":"invalid-argument-format","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"}