pentaho/pentaho-kettle · error · KettleException

SSH.Error.PrivateKeyFileMissing

SSH.Error.PrivateKeyFileMissing

Error message

SSH.Error.PrivateKeyFileMissing

What it means

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.

Solutions

  1. Set the private key file field in the step dialog to a valid path (e.g. /home/user/.ssh/id_rsa)
  2. If using a variable like ${Internal...} or a parameter, define it in the transformation settings or runtime configuration
  3. Switch to password authentication if a key is not actually intended

Example fix

// before
String keyFilename = ""; // empty -> throws
// after
String keyFilename = "${USER_HOME}/.ssh/id_rsa"; // set in dialog, variable defined
Defensive patterns

Strategy: validation

Validate before calling

if (keyFileField == null || keyFileField.trim().isEmpty()) {
  throw new IllegalArgumentException("Private key file path must be set for key auth");
}

Prevention

When it happens

Trigger: Choosing 'private key' authentication in the SSH step while leaving the key file field blank (or a variable that resolves to empty).

Common situations: Copy-pasting step settings and forgetting to set the key path; relying on a parameter/variable that was never defined in the runtime environment.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/ssh/SSHData.java:186

  private static void configureAuthentication( SshConfig config, Bowl bowl, boolean useKey,
      String keyFilename, String passPhrase, String password, VariableSpace space ) throws KettleException {

    if ( useKey ) {
      configureKeyAuthentication( config, bowl, keyFilename, passPhrase, space );
    } else {
      config.authType( SshConfig.AuthType.PASSWORD ).password( password );
    }
  }

  /**
   * Configures key-based authentication using secure in-memory key handling.
   * This avoids writing sensitive key data to temporary files on the filesystem.
   */
  private static void configureKeyAuthentication( SshConfig config, Bowl bowl,
      String keyFilename, String passPhrase, VariableSpace space ) throws KettleException {

    if ( Utils.isEmpty( keyFilename ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "SSH.Error.PrivateKeyFileMissing" ) );
    }

    try {
      FileObject keyFileObject = KettleVFS.getInstance( bowl ).getFileObject( keyFilename );
      if ( !keyFileObject.exists() ) {
        throw new KettleException( BaseMessages.getString( PKG, "SSH.Error.PrivateKeyNotExist", keyFilename ) );
      }

      // Read key file content into memory - no temporary file needed
      FileContent keyFileContent = keyFileObject.getContent();
      byte[] keyBytes;
      try ( InputStream in = keyFileContent.getInputStream() ) {
        keyBytes = in.readAllBytes();
        if ( keyBytes.length == 0 ) {
          throw new KettleException( BaseMessages.getString( PKG, "SSH.Error.ProcessingKeyFile", keyFilename ) );
        }
      }

View on GitHub (pinned to f3058517a1)