{"record":{"id":"7715ada8a7a3a55e","repo":"pentaho/pentaho-kettle","slug":"gpg-ioexception","errorCode":null,"errorMessage":"GPG.IOException","messagePattern":"GPG\\.IOException","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/job/entries/pgpencryptfiles/GPG.java","lineNumber":184,"sourceCode":"   */\n  private String execGnuPG( String commandArgs, String inputStr, boolean fileMode ) throws KettleException {\n    Process p;\n    String command = getGpgExeFile() + \" \" + ( fileMode ? \"\" : gnuPGCommand + \" \" ) + commandArgs;\n\n    if ( log.isDebug() ) {\n      log.logDebug( BaseMessages.getString( PKG, \"GPG.RunningCommand\", command ) );\n    }\n    String retval;\n\n    try {\n      if ( Const.isWindows() ) {\n        p = Runtime.getRuntime().exec( command );\n      } else {\n        ProcessBuilder processBuilder = new ProcessBuilder( \"/bin/sh\", \"-c\", command );\n        p = processBuilder.start();\n      }\n    } catch ( IOException io ) {\n      throw new KettleException( BaseMessages.getString( PKG, \"GPG.IOException\" ), io );\n    }\n\n    ProcessStreamReader psr_stdout = new ProcessStreamReader( p.getInputStream() );\n    ProcessStreamReader psr_stderr = new ProcessStreamReader( p.getErrorStream() );\n    psr_stdout.start();\n    psr_stderr.start();\n    if ( inputStr != null ) {\n      BufferedWriter out = new BufferedWriter( new OutputStreamWriter( p.getOutputStream() ) );\n      try {\n        out.write( inputStr );\n      } catch ( IOException io ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"GPG.ExceptionWrite\" ), io );\n      } finally {\n        if ( out != null ) {\n          try {\n            out.close();\n          } catch ( Exception e ) {\n            // Ignore","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/job/entries/pgpencryptfiles/GPG.java#L166-L202","documentation":"Thrown by GPG.execGnuPG when spawning the gpg command-line process fails with a java.io.IOException. The gpg binary is invoked via Runtime.exec or ProcessBuilder (/bin/sh -c on non-Windows); if process creation fails, this wrapped KettleException is raised.","triggerScenarios":"Runtime.getRuntime().exec(command) or processBuilder.start() throws IOException — the executable path is invalid at exec time, working directory inaccessible, too many open files, or (on some JVMs) Command file creation fails.","commonSituations":"GPG binary deleted/moved between validation and execution; insufficient OS file descriptors (ulimit) under load; execute permission removed from the binary; container images without /bin/sh when ProcessBuilder path is used; ENOMEM/process limits hit.","solutions":["Confirm the gpg executable still exists and is executable at runtime (chmod +x, correct path).","Check the wrapped IOException (getCause()) for errno details (ENOENT, EACCES, EMFILE).","Raise the file-descriptor limit (ulimit -n) if EMFILE/too many open files is reported.","On Windows ensure the path is quoted correctly; on non-Windows ensure /bin/sh exists in the runtime environment/container."],"exampleFix":"// before\nString command = gpgexe + \" --decrypt \" + filename; // unquoted spaces break exec\n// after\nString command = \"\\\"\" + gpgexe + \"\\\" --decrypt \\\"\" + filename + \"\\\"\"; // quoted paths\np = Runtime.getRuntime().exec( command );","handlingStrategy":"try-catch","validationCode":"java.io.File gpg = new java.io.File( gpgexe );\nif ( !gpg.canExecute() ) throw new IllegalStateException( \"gpg not executable: \" + gpgexe );\n// check fd headroom\nif ( new java.io.File( \"/proc/self/fd\" ).list().length > 20000 ) log.warn( \"High fd usage; exec may fail\" );","typeGuard":"boolean canExecGpg( String p ) { return p != null && new java.io.File( p ).canExecute(); }","tryCatchPattern":"try {\n  gpg.execGnuPG( args );\n} catch ( KettleException e ) {\n  if ( e.getCause() instanceof java.io.IOException ) {\n    java.io.IOException io = (java.io.IOException) e.getCause();\n    logError( \"Failed to launch gpg: \" + io.getMessage() + \" — check path, permissions, and ulimit\" );\n  }\n}","preventionTips":["Verify the gpg binary exists and is executable immediately before execution.","Raise ulimit -n on hosts running many GPG operations.","Ensure /bin/sh exists in containers used on non-Windows platforms.","Quote executable and file paths to survive spaces.","Check the wrapped IOException errno to target the fix."],"tags":["gpg","process-execution","io","gnupg"],"backgroundTag":"command-not-found","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"}