pentaho/pentaho-kettle · warning · KettleException

GPG.ExceptionillegalThreadStateException

Error message

GPG.ExceptionillegalThreadStateException

What it means

KettleException with key GPG.ExceptionillegalThreadStateException is thrown by GPG.execGnuPG when p.exitValue() is called while the gpg process has not yet terminated (IllegalThreadStateException). This indicates a race in the code: waitFor() succeeded but a caller path reaches exitValue() before the process is truly done. The process is destroyed in the finally block.

Solutions

  1. Replace p.exitValue() with the int returned by p.waitFor(), which cannot throw IllegalThreadStateException.
  2. Ensure psr_stdout.join()/psr_stderr.join() completed before checking exit status.
  3. If it recurs, capture the gpg command line and run it manually to check for hangs.
  4. Upgrade the Pentaho Kettle engine version where this race may be fixed.

Example fix

// before
p.waitFor();
...
if ( p.exitValue() != 0 ) {
// after
int exitCode = p.waitFor();
...
if ( exitCode != 0 ) {
Defensive patterns

Strategy: try-catch

Try / catch

try {
  gpg.signFile(file, userId, signedFile, false);
} catch (KettleException ke) {
  if (ke.getCause() instanceof IllegalThreadStateException) {
    // process state race — retry once
  }
}

Prevention

When it happens

Trigger: Any of decryptFile, encryptFile, signAndEncryptFile, signFile, verifySignature, verifyDetachedSignature when p.exitValue() is queried before the gpg process has exited.

Common situations: Rare JVM/threading timing issue after waitFor(); abnormal gpg process states; heavily loaded systems where thread joins return while process bookkeeping lags.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/pgpencryptfiles/GPG.java:223

      }
    }

    try {
      p.waitFor();

      psr_stdout.join();
      psr_stderr.join();
    } catch ( InterruptedException i ) {
      throw new KettleException( BaseMessages.getString( PKG, "GPG.ExceptionWait" ), i );
    }

    try {
      if ( p.exitValue() != 0 ) {
        throw new KettleException( BaseMessages.getString( PKG, "GPG.Exception.ExistStatus", psr_stderr
          .getString() ) );
      }
    } catch ( IllegalThreadStateException itse ) {
      throw new KettleException( BaseMessages.getString( PKG, "GPG.ExceptionillegalThreadStateException" ), itse );
    } finally {
      p.destroy();
    }

    retval = psr_stdout.getString();

    return retval;

  }

  /**
   * Decrypt a file
   *
   * @param cryptedFilename
   *          crypted filename
   * @param passPhrase
   *          passphrase for the personal private key to sign with
   * @param decryptedFilename

View on GitHub (pinned to f3058517a1)