pentaho/pentaho-kettle · error · KettleDatabaseException
Dynamic driver for ' ' has been unloaded (disconnect was…
Error message
Dynamic driver for '{effectiveClassName}' has been unloaded (disconnect was called concurrently). Reconnect to reload the driver. What it means
The dynamic driver instance is held in a per-connection AtomicReference (dynamicDriver). openConnectionViaDriver requires it to be non-null; if another thread called disconnect() concurrently the driver was unloaded and this error is thrown instead of dereferencing null. It is a race/-state error indicating the connection is closing while a connect is still in flight.
Solutions
- Reconnect — a fresh connect() reloads the dynamic driver automatically
- Ensure each Database instance is used by a single thread or properly synchronized
- Avoid calling disconnect() while connect() is in flight on the same Database object
- Do not share one Database instance across concurrently executing transformations/jobs
Example fix
// before new Thread(() -> db.disconnect()).start(); Connection c = db.getConnection(); // races disconnect // after db.disconnect(); // ensure fully closed Database db2 = new Database(...); db2.connect(); // fresh instance
Defensive patterns
Strategy: try-catch
Try / catch
try { conn = db.getConnection(); } catch (KettleDatabaseException e) { if (e.getMessage().contains("has been unloaded (disconnect was called concurrently)")) { log.warn("Concurrent disconnect during connect — reconnecting"); db = new Database(...); conn = db.getConnection(); } else throw e; } Prevention
- Use each Database instance from a single thread
- Do not call disconnect() while connect()/getConnection() is in flight
- Centralize connection lifecycle management (one owner per connection)
- Avoid sharing Database instances across steps/threads
When it happens
Trigger: Calling connect() on a Database whose disconnect() runs concurrently (or already ran) so dynamicDriver was cleared to null before openConnectionViaDynamicDriver reads it.
Common situations: Trans pipelines canceling/aborting a step while it is still opening the connection; timeout watchdog closing connections; double lifecycle management (framework and user code both calling disconnect); shared Database instance across threads.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- AccessInputMeta.Exception.ErrorSavingToRepository
- An error occurred executing SQL:
- An error occurred executing SQL:
- Cannot fetch driver metadata for
- Command execution was interrupted
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/cc68c2146f65e415.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:939
} catch ( Exception ignored ) {
// best-effort
}
}
throw new KettleDatabaseException(
"Dynamic driver: failed to load '" + effectiveClassName + "' from '" + resolvedPath + "': " + e.getMessage(), e );
}
}
}
/**
* Opens a JDBC connection via the already-loaded {@link #dynamicDriver}, bypassing
* {@link DriverManager}. Validates URL acceptance before connecting.
*/
private Connection openConnectionViaDynamicDriver( String effectiveClassName, String url, Properties properties )
throws KettleDatabaseException {
Driver localDriver = dynamicDriver.get();
if ( localDriver == null ) {
throw new KettleDatabaseException(
"Dynamic driver for '" + effectiveClassName + "' has been unloaded (disconnect was called concurrently). "
+ "Reconnect to reload the driver." );
}
boolean accepts;
try {
accepts = localDriver.acceptsURL( url );
} catch ( Exception e ) {
throw new KettleDatabaseException(
"Dynamic driver '" + effectiveClassName + "' threw exception checking URL '"
+ 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 );View on GitHub (pinned to f3058517a1)