pentaho/pentaho-kettle · error · KettleDatabaseException

Cannot fetch driver metadata for

Error message

Cannot fetch driver metadata for '{driverId}': JDBC_DRIVER_SERVICE_URL is not configured. Set the environment variable or system property 'JDBC_DRIVER_SERVICE_URL'.

What it means

getMetadataFromDriver requires a base URL for the remote driver-metadata service, read via Const.getJdbcDriverServiceUrl() (env var or system property JDBC_DRIVER_SERVICE_URL). When it is unset or blank the method fails fast with this error before making any HTTP call. It is a configuration precondition, not a network failure.

Solutions

  1. Set the environment variable JDBC_DRIVER_SERVICE_URL to the metadata service base URL (e.g. http://metadata-service:8080)
  2. Or pass the Java system property -DJDBC_DRIVER_SERVICE_URL=http://metadata-service:8080 on startup
  3. Verify the value is non-blank at startup (fail fast in launcher scripts)
  4. If metadata is optional for your deployment, ensure the calling code path handles/disables driver metadata lookup

Example fix

// before
pdi.sh  # JDBC_DRIVER_SERVICE_URL unset
// after
export JDBC_DRIVER_SERVICE_URL=http://driver-metadata:8080
./pdi.sh
Defensive patterns

Strategy: validation

Validate before calling

String url = System.getenv("JDBC_DRIVER_SERVICE_URL");
if (url == null) url = System.getProperty("JDBC_DRIVER_SERVICE_URL");
if (url == null || url.trim().isEmpty()) throw new IllegalStateException("JDBC_DRIVER_SERVICE_URL must be set before connecting");

Type guard

boolean hasDriverServiceUrl() { String u = Const.getJdbcDriverServiceUrl(); return u != null && !u.trim().isEmpty(); }

Try / catch

try { map = db.driverMetadata(driverId); } catch (KettleDatabaseException e) { if (e.getMessage().contains("JDBC_DRIVER_SERVICE_URL is not configured")) { log.error("Set JDBC_DRIVER_SERVICE_URL env/system property"); } else throw e; }

Prevention

When it happens

Trigger: Calling driverMetadata (e.g. when resolving a dynamic driver's metadata) while JDBC_DRIVER_SERVICE_URL is neither set as an environment variable nor as a -D system property, or is set to whitespace only.

Common situations: Fresh install/CI container where the service URL was never provisioned; renaming the env var in deployment configs; running Pentaho locally without the metadata service config; YAML/k8s manifest missing the env entry.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:732

  }

  private String appendMssqlInstanceIfNeeded( String url ) {
    if ( databaseMeta.getDatabaseInterface() instanceof MSSQLServerNativeDatabaseMeta ) {
      // Handle MSSQL Instance name. Would rather this was handled in the dialect
      // but cannot (without refactor) get to variablespace for variable substitution from
      // a BaseDatabaseMeta subclass.
      String instance = environmentSubstitute( databaseMeta.getSQLServerInstance() );
      if ( !Utils.isEmpty( instance ) ) {
        return url + ";instanceName=" + instance;
      }
    }
    return url;
  }

  private static Map<String, Object> getMetadataFromDriver( String driverId ) throws KettleDatabaseException {
    String serviceBaseUrl = Const.getJdbcDriverServiceUrl();
    if ( serviceBaseUrl == null || serviceBaseUrl.trim().isEmpty() ) {
      throw new KettleDatabaseException(
        "Cannot fetch driver metadata for '" + driverId + "': JDBC_DRIVER_SERVICE_URL is not configured. "
          + "Set the environment variable or system property 'JDBC_DRIVER_SERVICE_URL'." );
    }

    String metadataUrl = serviceBaseUrl + "/api/v1/connection-drivers/" + driverId;
    HttpURLConnection conn = null;
    try {
      conn = (HttpURLConnection) new URL( metadataUrl ).openConnection();
      conn.setConnectTimeout( 10_000 );
      conn.setReadTimeout( 60_000 );
      conn.setRequestMethod( "GET" );

      String bearerToken = CmsTokenProvider.getInstance().getToken();
      if ( bearerToken != null ) {
        conn.setRequestProperty( "Authorization", "Bearer " + bearerToken );
      }

      int status = conn.getResponseCode();

View on GitHub (pinned to f3058517a1)