pentaho/pentaho-kettle · error · KettleDatabaseException

BaseMessages.getString( packageClass, key, parameters )…

Error message

BaseMessages.getString( packageClass, key, parameters ) (localized message, dynamic)

What it means

DatabaseLogExceptionFactory's ThrowableBehaviour registers a database log record and throws a KettleDatabaseException whose message is produced by BaseMessages.getString(packageClass, key, parameters) — a localized message looked up from a message bundle with optional {0}-style parameters. It is thrown so the caller sees a localized, formatted error while the same text is written to the log channel.

Solutions

  1. Fix the packageClass/key pair so it matches an entry in the bundle's messages.properties files.
  2. Verify the parameter count matches the placeholders in the localized message.
  3. Check the kettle locales directory contains the properties file for packageClass on the classpath.
  4. Catch KettleDatabaseException at the call site and log the actual cause if the localized message is unhelpful.

Example fix

// before
DatabaseLogExceptionFactory.getExceptionBehaviour().registerException(log, PKG, "MyPlugin.WrongKey.Error");
// after
DatabaseLogExceptionFactory.getExceptionBehaviour().registerException(log, PKG, "MyPlugin.ConnectionFailed.Error", tableName);
Defensive patterns

Strategy: try-catch

Validate before calling

// validate the key exists before calling
String msg = BaseMessages.getString( PKG, "MyPlugin.ConnectionFailed.Error" );
if ( msg.startsWith( "!" ) ) throw new IllegalStateException( "Missing message key" );

Try / catch

try {
  behaviour.registerException( log, PKG, KEY, params );
} catch ( KettleDatabaseException e ) {
  log.logError( "DB operation failed", e );
  // inspect e.getMessage() and the message bundle
}

Prevention

When it happens

Trigger: Calling DatabaseLogExceptionFactory.registerException(log, packageClass, key, parameters...) (or the overload with a cause Exception) where the given key exists or is missing in the packageClass message bundle; any runtime failure in BaseMessages lookup formatting also surfaces here.

Common situations: Plugin code using the exception factory with a typo'd message key or wrong packageClass, or passing parameters that don't match the bundle placeholders, yielding 'Message not found in key' style output wrapped in a KettleDatabaseException.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/util/DatabaseLogExceptionFactory.java:121

  private static DatabaseInterfaceExtended extractDatabase( LogTableCoreInterface table ) {
    DatabaseInterfaceExtended result = null;
    if ( table != null && table.getDatabaseMeta() != null ) {
      DatabaseInterface databaseInterface = table.getDatabaseMeta().getDatabaseInterface();
      result =
          databaseInterface instanceof DatabaseInterfaceExtended ? (DatabaseInterfaceExtended) databaseInterface : null;
    }
    return result;
  }

  /**
   * Throw exception back to caller, this will be logged somewhere else.
   */
  private static class ThrowableBehaviour implements LogExceptionBehaviourInterface {

    @Override
    public void registerException( LogChannelInterface log, Class<?> packageClass, String key, String... parameters )
        throws KettleDatabaseException {
      throw new KettleDatabaseException( BaseMessages.getString( packageClass, key, parameters ) );
    }

    @Override public void registerException( LogChannelInterface log, Exception e, Class<?> packageClass, String key,
        String... parameters ) throws KettleDatabaseException {
      throw new KettleDatabaseException( BaseMessages.getString( packageClass, key, parameters ), e );
    }
  }

  /**
   * Suppress exception, but still add a log record about it
   */
  private static class SuppressBehaviour implements LogExceptionBehaviourInterface {

    @Override
    public void registerException( LogChannelInterface log, Class<?> packageClass, String key, String... parameters ) {
      log.logError( BaseMessages.getString( packageClass, key, parameters ) );
    }

View on GitHub (pinned to f3058517a1)