pentaho/pentaho-kettle · error · KettleDatabaseException

JdbcDriverResolver: driverId must not be null or blank

Error message

JdbcDriverResolver: driverId must not be null or blank

What it means

JdbcDriverResolver.resolve(driverId) requires a non-null, non-blank driver identifier because it is used to build the JAR file name (driverId + ".jar") and the download URL. It performs a fail-fast guard at the top of the method, throwing KettleDatabaseException when the argument is null, empty, or whitespace.

Solutions

  1. Ensure the caller supplies a valid driverId before calling resolve
  2. Default the driverId from the DatabaseMeta (e.g. connection's getDriverClass()) when missing
  3. Trim user-supplied input and reject blank values upstream with a clearer UI error

Example fix

// before
String path = JdbcDriverResolver.resolve( driverId ); // NPE-adjacent blank input
// after
if ( driverId == null || driverId.trim().isEmpty() ) {
  throw new IllegalArgumentException( "driverId is required (e.g. postgresql)" );
}
String path = JdbcDriverResolver.resolve( driverId.trim() );
Defensive patterns

Strategy: validation

Validate before calling

if ( driverId == null || driverId.trim().isEmpty() ) {
  throw new IllegalArgumentException( "driverId is required before resolving a driver JAR" );
}

Type guard

boolean isValidDriverId( String s ) { return s != null && !s.trim().isEmpty(); }

Try / catch

try { path = JdbcDriverResolver.resolve( driverId ); } catch ( KettleDatabaseException e ) { failFast( "blank/invalid driverId: " + driverId ); }

Prevention

When it happens

Trigger: Calling JdbcDriverResolver.resolve(null) or resolve("") or resolve(" ") — typically when the database type has no mapped driverId, or the caller passes an uninitialized field from configuration.

Common situations: DatabaseMeta with an unset/blank driver class; a scripting step building the driverId dynamically from user input; resolveAll() given a list containing blank entries (though resolveAll skips those).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/JdbcDriverResolver.java:97

   */
  private static final ConcurrentHashMap<String, ReentrantLock> DOWNLOAD_LOCKS = new ConcurrentHashMap<>();

  private JdbcDriverResolver() {
    // utility class
  }

  /**
   * Returns an absolute path to the JDBC driver JAR.
   *
   * <p>If {@code driverId} points to an existing file it is returned immediately.
   * Otherwise the resolution chain described in the class Javadoc is followed.
   *
   * @return absolute path of the resolved JAR file
   * @throws KettleDatabaseException if the JAR cannot be found or downloaded
   */
  public static String resolve( String driverId ) throws KettleDatabaseException {
    if ( driverId == null || driverId.trim().isEmpty() ) {
      throw new KettleDatabaseException( "JdbcDriverResolver: driverId must not be null or blank" );
    }
    String configuredPath = driverId + ".jar";
    // 1 — configured path exists as-is
    if ( existsAsFile( configuredPath ) ) {
      return configuredPath;
    }

    String jarName = Paths.get( configuredPath ).getFileName().toString();
    log.logBasic( "JdbcDriverResolver: JAR not found at configured path '" + configuredPath
      + "' — searching by file name '" + jarName + "'" );

    // 2 — JDBC_DRIVERS_DIRECTORY: env var wins over system property (via Const)
    String resolved = tryDirectory( Const.getJdbcDriversDirectory(), jarName, "Const.getJdbcDriversDirectory()" );
    if ( resolved != null ) {
      return resolved;
    }

    // 3 — JDBC_DRIVERS_DIRECTORY from kettle.properties (on-prem / BA Server)

View on GitHub (pinned to f3058517a1)