pentaho/pentaho-kettle · error · KettleException

Rest.Error.CertificateException

Rest.Error.CertificateException

Error message

Rest.Error.CertificateException

What it means

setSSLConfiguration wraps java.security.cert.CertificateException from HttpClientManager.getSslContext in a KettleException with Rest.Error.CertificateException. The trust store's certificates could not be parsed/loaded — the file contains malformed or unreadable certificate data.

Solutions

  1. Verify the trust store with keytool -list; recreate it if entries are corrupt
  2. Import the certificate cleanly: keytool -importcert -alias server -file server.crt -keystore truststore.p12 -storetype PKCS12
  3. Transfer the file in binary mode / re-download it if it was corrupted in transit
  4. Confirm the file is a real keystore, not a bare PEM certificate
  5. Check the cause chain for which certificate entry failed to parse

Example fix

// before
# using a PEM file directly as trust store
TrustStore File: server.crt
// after
keytool -importcert -alias server -file server.crt -keystore truststore.p12 -storetype PKCS12 -storepass changeit
TrustStore File: truststore.p12
Defensive patterns

Strategy: validation

Validate before calling

// confirm the trust store's certificates parse before the step loads them
java.security.KeyStore ks = java.security.KeyStore.getInstance( "PKCS12" );
try ( var in = new java.io.FileInputStream( trustStoreFile ) ) {
  ks.load( in, password );
  if ( ks.size() == 0 ) {
    throw new IllegalStateException( "Trust store contains no certificates" );
  }
} // CertificateException here means corrupt/malformed entries

Try / catch

try {
  step.setConfig( meta, data, row );
} catch ( KettleException e ) {
  if ( e.getMessage().contains( "CertificateException" ) ) {
    log.error( "Trust store has malformed certificates — re-import the server cert", e );
  }
}

Prevention

When it happens

Trigger: Trust store contains a corrupted or non-DER/PEM certificate entry; the file is a raw certificate rather than a keystore; certificate entries damaged during transfer (e.g. FTP ASCII mode, copy-paste).

Common situations: Exported certificate pasted into a text editor altering line endings; a PEM chain saved with a .jks extension and passed as a trust store; partially downloaded trust store file.

Understand the failure class

Related errors


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

Appendix: source

Thrown at plugins/rest/core/src/main/java/org/pentaho/di/trans/steps/rest/Rest.java:369

        }
      }
      // SSL TRUST STORE CONFIGURATION
      setSSLConfiguration( data );
    }
  }

  protected void setSSLConfiguration( RestData data ) throws KettleException {
    try ( var trustStoreIn = getInputStream( data.trustStoreFile ) ) {
      data.sslContext = HttpClientManager.getSslContext( meta.isIgnoreSsl(),
        trustStoreIn,
        data.trustStorePassword );

    } catch ( NoSuchAlgorithmException e ) {
      throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.NoSuchAlgorithm" ), e );
    } catch ( KeyStoreException e ) {
      throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.KeyStoreException" ), e );
    } catch ( CertificateException e ) {
      throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.CertificateException" ), e );
    } catch ( FileNotFoundException e ) {
      throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.FileNotFound", data.trustStoreFile ), e );
    } catch ( IOException e ) {
      throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.IOException" ), e );
    } catch ( KeyManagementException | UnrecoverableKeyException e ) {
      throw new KettleException( BaseMessages.getString( PKG, "Rest.Error.KeyManagementException" ), e );
    }
  }

  /**
   * Get an InputStream for the file with the given name.
   * If the file name is empty or null, returns null.
   *
   * @param fileName the file name to get InputStream from
   * @return InputStream for the given file, <code>null</code> if the given file name is empty or null
   * @throws KettleException if any error occurs while getting the InputStream
   */
  protected InputStream getInputStream( String fileName ) throws KettleException {

View on GitHub (pinned to f3058517a1)