{"record":{"id":"1c25a577b292552d","repo":"pentaho/pentaho-kettle","slug":"ssh-error-privatekeyfilemissing","errorCode":"SSH.Error.PrivateKeyFileMissing","errorMessage":"SSH.Error.PrivateKeyFileMissing","messagePattern":"SSH\\.Error\\.PrivateKeyFileMissing","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/ssh/SSHData.java","lineNumber":186,"sourceCode":"  private static void configureAuthentication( SshConfig config, Bowl bowl, boolean useKey,\n      String keyFilename, String passPhrase, String password, VariableSpace space ) throws KettleException {\n\n    if ( useKey ) {\n      configureKeyAuthentication( config, bowl, keyFilename, passPhrase, space );\n    } else {\n      config.authType( SshConfig.AuthType.PASSWORD ).password( password );\n    }\n  }\n\n  /**\n   * Configures key-based authentication using secure in-memory key handling.\n   * This avoids writing sensitive key data to temporary files on the filesystem.\n   */\n  private static void configureKeyAuthentication( SshConfig config, Bowl bowl,\n      String keyFilename, String passPhrase, VariableSpace space ) throws KettleException {\n\n    if ( Utils.isEmpty( keyFilename ) ) {\n      throw new KettleException( BaseMessages.getString( PKG, \"SSH.Error.PrivateKeyFileMissing\" ) );\n    }\n\n    try {\n      FileObject keyFileObject = KettleVFS.getInstance( bowl ).getFileObject( keyFilename );\n      if ( !keyFileObject.exists() ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"SSH.Error.PrivateKeyNotExist\", keyFilename ) );\n      }\n\n      // Read key file content into memory - no temporary file needed\n      FileContent keyFileContent = keyFileObject.getContent();\n      byte[] keyBytes;\n      try ( InputStream in = keyFileContent.getInputStream() ) {\n        keyBytes = in.readAllBytes();\n        if ( keyBytes.length == 0 ) {\n          throw new KettleException( BaseMessages.getString( PKG, \"SSH.Error.ProcessingKeyFile\", keyFilename ) );\n        }\n      }\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/ssh/SSHData.java#L168-L204","documentation":"SSH.Error.PrivateKeyFileMissing is thrown by configureKeyAuthentication when key-based authentication is selected but the private key filename field is empty or null. The step cannot attempt key authentication without a key path, so it fails fast before touching the filesystem.","triggerScenarios":"Choosing 'private key' authentication in the SSH step while leaving the key file field blank (or a variable that resolves to empty).","commonSituations":"Copy-pasting step settings and forgetting to set the key path; relying on a parameter/variable that was never defined in the runtime environment.","solutions":["Set the private key file field in the step dialog to a valid path (e.g. /home/user/.ssh/id_rsa)","If using a variable like ${Internal...} or a parameter, define it in the transformation settings or runtime configuration","Switch to password authentication if a key is not actually intended"],"exampleFix":"// before\nString keyFilename = \"\"; // empty -> throws\n// after\nString keyFilename = \"${USER_HOME}/.ssh/id_rsa\"; // set in dialog, variable defined","handlingStrategy":"validation","validationCode":"if (keyFileField == null || keyFileField.trim().isEmpty()) {\n  throw new IllegalArgumentException(\"Private key file path must be set for key auth\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never leave the key path blank when auth type is private key","Use defined Kettle variables/parameters for the key path and verify they resolve","Document required parameters per environment"],"tags":["ssh","authentication","missing-config"],"backgroundTag":"missing-required-config-field","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"}