{"record":{"id":"c35550d74eb03871","repo":"pentaho/pentaho-kettle","slug":"ssh-error-processingkeyfile","errorCode":"SSH.Error.ProcessingKeyFile","errorMessage":"SSH.Error.ProcessingKeyFile","messagePattern":"SSH\\.Error\\.ProcessingKeyFile","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/ssh/SSHData.java","lineNumber":201,"sourceCode":"      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\n      // Configure SSH with in-memory key content - secure approach\n      config.authType( SshConfig.AuthType.PUBLIC_KEY ).keyContent( keyBytes );\n\n      if ( !Utils.isEmpty( passPhrase ) ) {\n        config.passphrase( space.environmentSubstitute( passPhrase ) );\n      }\n\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString( PKG, \"SSH.Error.ProcessingKeyFile\", keyFilename ), e );\n    }\n  }\n\n  /**\n   * Configures proxy settings for the SSH connection.\n   */","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/ssh/SSHData.java#L183-L219","documentation":"SSH.Error.ProcessingKeyFile is thrown when the private key file exists but its content is empty: reading the file stream produced zero bytes. The step treats an empty key file as unusable and fails with this error, naming the key file.","triggerScenarios":"The key file path resolves to an existing but zero-byte file (truncate, failed copy, mount issue, or a placeholder file).","commonSituations":"CI secrets mounted as empty files when the secret is missing; interrupted scp/copy that left a 0-byte key; a directory mis-typed accidentally resolving oddly on some VFS layers.","solutions":["Verify the key file has content (`wc -c id_rsa` / `ls -l`) and re-copy a valid private key","Check that the CI/CD secret or mount that provides the key is actually populated","Regenerate the key pair and deploy the new private key"],"exampleFix":"// before\n-rw------- 0 bytes id_rsa  (empty file -> throws)\n// after\nscp valid_id_rsa worker:/opt/pentaho/keys/id_rsa  # non-empty key file","handlingStrategy":"validation","validationCode":"java.io.File f = new java.io.File(environmentSubstitute(keyFileField));\nif (f.length() == 0) {\n  throw new IllegalStateException(\"Private key file is empty: \" + f.getAbsolutePath());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check key file sizes after deployment/secrets mount","Fail CI early if mounted secrets are empty","Re-copy keys after any interrupted transfer"],"tags":["ssh","authentication","empty-file"],"backgroundTag":"file-read-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"}