pentaho/pentaho-kettle · error · KettleDatabaseException
Dynamic driver ' ' failed to connect to URL
Error message
Dynamic driver '{effectiveClassName}' failed to connect to URL '{url}': {errorMsg} What it means
KettleDatabaseException thrown by Database.connect() when a dynamically loaded JDBC driver class fails to open a connection to the given URL. It wraps the underlying driver exception (errorMsg(e)) so the root cause (bad URL, driver mismatch, network, auth) is preserved. It only fires on the dynamic-driver code path after the class was loaded but DriverManager.getConnection failed.
Solutions
- Verify the JDBC URL format against the driver's documentation and correct databaseMeta URL/hostname/port/database
- Confirm the DB server is running and reachable (ping/telnet host port)
- Check username/password are correct for the target database
- Verify the driver jar version supports the URL syntax being used; upgrade or correct the driver plugin
- Inspect the wrapped cause exception (getCause()) for the driver's own error message
Example fix
// before
databaseMeta.setURL("jdbc:mysql//host:3306/db");
// after
databaseMeta.setURL("jdbc:mysql://host:3306/db"); Defensive patterns
Strategy: try-catch
Validate before calling
String url = databaseMeta.getURL();
if ( url == null || !url.startsWith( "jdbc:" ) ) {
throw new IllegalArgumentException( "Invalid JDBC URL: " + url );
} Type guard
boolean isValidJdbcUrl( String url ) {
return url != null && url.matches( "jdbc:[a-zA-Z0-9]+://.+" );
} Try / catch
try {
database.connect();
} catch ( KettleDatabaseException e ) {
Throwable cause = e.getCause();
log.error( "Driver connect failed: " + cause.getMessage(), cause );
throw new RuntimeException( "Check JDBC URL, driver and DB availability", e );
} Prevention
- Validate the JDBC URL format against driver docs before connecting
- Health-check DB host/port (telnet) before starting the transformation
- Pin a driver version known to work with the URL syntax
- Log getCause() to surface the driver's real error
When it happens
Trigger: Calling Database.connect() (or connectAnon) where databaseMeta uses a dynamic/plugin driver: the driver class loaded but DriverManager.getConnection(url, props) threw — wrong JDBC URL format, driver does not accept the URL scheme, DB down/unreachable, or bad credentials.
Common situations: Typo in the JDBC URL (jdbc:mysql:// vs jdbc:postgresql://), wrong port, firewall/DNS failure, database stopped, driver jar version incompatible with the URL syntax, or special characters in password not escaped.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Database.Exception.EmptyConnectionError
- Dynamic driver ' ' returned null for URL: — check that the…
- LucidDBStreamingLoaderMeta.Exception.ErrorGettingFields
- An error occurred executing SQL:
- An error occurred executing SQL:
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/e4aa834748b0efe5.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:967
+ url + "': " + errorMsg( e ), e );
}
if ( !accepts ) {
throw new KettleDatabaseException(
"Dynamic driver '" + effectiveClassName + "' does not accept URL: " + url
+ " — check the JDBC URL format." );
}
try {
Connection c = localDriver.connect( url, properties );
if ( c == null ) {
throw new KettleDatabaseException(
"Dynamic driver '" + effectiveClassName + "' returned null for URL: " + url
+ " — check that the URL format and driver class are correct." );
}
return c;
} catch ( KettleDatabaseException e ) {
throw e;
} catch ( Exception e ) {
throw new KettleDatabaseException(
"Dynamic driver '" + effectiveClassName + "' failed to connect to URL '"
+ url + "': " + errorMsg( e ), e );
}
}
/**
* Returns the exception message, or the simple class name when the message is null.
* Avoids repetitive inline ternary expressions in error-handling code.
*/
private static String errorMsg( Exception e ) {
return e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
}
@Override
public void close() {
disconnect();
}View on GitHub (pinned to f3058517a1)