pentaho/pentaho-kettle · error · KettleDatabaseException
Error closing
Error message
Error closing
What it means
Database.tryCloseAndThrow wraps any Exception thrown by AutoCloseable.close() (e.g. a JDBC PreparedStatement, Statement or ResultSet) into a KettleDatabaseException whose message is 'Error closing ' + the object description. It is thrown when releasing a JDBC resource fails, usually because the underlying connection is already broken or the statement is in an invalid state. The original exception is preserved as the cause.
Solutions
- Check the cause exception: if it says 'Connection is closed' or similar, the real problem is the lost connection — verify DB availability and network before blaming close()
- Ensure the Database connection is still open and commit/rollback was done before closing statements
- Avoid closing the same Database/statement resources twice in finally blocks
- Check driver version compatibility; upgrade the JDBC driver if close() spuriously fails
- Wrap close calls in a null-check/try-ignore so cleanup failures don't mask the original step error
Example fix
// before
database.closeInsert();
// after
try {
database.closeInsert();
} catch (KettleDatabaseException e) {
log.logError("Ignoring failure while closing insert statement", e);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (database != null && !database.isAutoCommit()) { /* ensure commit/rollback done before close */ } Try / catch
try {
database.closeInsert();
} catch (KettleDatabaseException e) {
log.logError("Failed closing insert statement: " + e.getMessage(), e);
// inspect e.getCause() for the underlying SQLException
} Prevention
- Commit or rollback before closing statements
- Never close the same statement/Database twice
- Monitor DB connection health during long runs
- Keep JDBC drivers up to date
When it happens
Trigger: Calling closeInsert(), closeUpdate(), closeLookup() or any Database.close*() path that routes through tryCloseAndThrow when the underlying JDBC statement's close() throws SQLException — typically because the connection was already closed, dropped by the DB, or the statement was already closed in an invalid transaction state.
Common situations: Database/network connection dropped mid-step before cleanup; connection pool forcibly closed the physical connection; calling close twice on the same statement; DB server restart during a long-running transformation; driver-specific errors on close after a failed execute.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Unable to close prepared statement pstmt
- Unable to close prepared statement sel_stmt
- Unable to close resultset
- 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/5429aaee78688cae.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/database/Database.java:1316
closeable.close();
} catch ( Exception ex ) {
log.logError( "Error closing " + objDescription + ":" + Const.CR + ex.getMessage() );
log.logError( Const.getStackTracker( ex ) );
}
}
/**
* Invokes the {@link AutoCloseable#close()} method on the given object, throwing a {@link KettleDatabaseException}
* encapsulating any exception that occurs.
*
* @param closeable the object to close
* @param objDescription the description of the closeable object, used in exception message
*/
protected void tryCloseAndThrow( AutoCloseable closeable, String objDescription ) throws KettleDatabaseException {
try {
closeable.close();
} catch ( Exception ex ) {
throw new KettleDatabaseException( "Error closing " + objDescription, ex );
}
}
public void closeInsert() throws KettleDatabaseException {
if ( prepStatementInsert != null ) {
tryCloseAndThrow( prepStatementInsert, "insert prepared statement" );
prepStatementInsert = null;
}
}
public void closeUpdate() throws KettleDatabaseException {
if ( prepStatementUpdate != null ) {
tryCloseAndThrow( prepStatementUpdate, "update prepared statement" );
prepStatementUpdate = null;
}
}
View on GitHub (pinned to f3058517a1)