pentaho/pentaho-kettle · error · KettleDatabaseException

Unable to close resultset

Error message

Unable to close resultset

What it means

Thrown by Database.getOneRow( String sql ) when the java.sql.ResultSet returned by openQuery cannot be closed (rs.close() throws). The row was already fetched, but the driver failed to release the resultset resource, so Kettle aborts with a KettleDatabaseException wrapping the underlying SQLException cause. It almost always reflects a connection or driver-level problem rather than bad SQL.

Solutions

  1. Check the wrapped cause (KettleDatabaseException.getCause()) to see the real SQLException and fix the underlying connection/driver issue
  2. Ensure the Database connection is open and healthy before calling getOneRow; reconnect with db.connect() if disconnect() was called or the connection timed out
  3. Upgrade the JDBC driver for the target database to a current version
  4. Avoid sharing a single Database instance across threads; use one instance per thread/execution

Example fix

// before
RowMetaAndData r = database.getOneRow( "SELECT COUNT(*) FROM t" ); // may throw on close
// after
RowMetaAndData r = null;
try {
  r = database.getOneRow( "SELECT COUNT(*) FROM t" );
} catch ( KettleDatabaseException e ) {
  logError( "Failed to fetch/close: " + e.getCause(), e );
  database.disconnect();
  database.connect();
  r = database.getOneRow( "SELECT COUNT(*) FROM t" );
}
Defensive patterns

Strategy: try-catch

Validate before calling

if ( database == null || !isConnected( database ) ) {
  throw new IllegalStateException( "Database connection is not open; call connect() before getOneRow()" );
}

Type guard

boolean isUsable( Database db ) {
  return db != null && db.getConnection() != null; // non-null open JDBC connection
}

Try / catch

try {
  RowMetaAndData row = database.getOneRow( sql );
} catch ( KettleDatabaseException e ) {
  Throwable cause = e.getCause();
  log.logError( "getOneRow cleanup failed: " + ( cause != null ? cause.getMessage() : e.getMessage() ), e );
  database.disconnect();
  database.connect();
  // retry once or degrade gracefully
}

Prevention

When it happens

Trigger: Calling db.getOneRow( sql ) where openQuery succeeded, getRow fetched a row, but ResultSet.close() threw — e.g. the JDBC connection was already closed/broken, the driver threw an SQL exception during close, or the statement/resultset was closed elsewhere concurrently.

Common situations: Connection dropped mid-operation (network timeout, server restart, wait_timeout expiry); calling getOneRow on a Database whose connection was disconnected beforehand; buggy or old JDBC drivers that throw on closing an exhausted resultset; concurrent use of one Database object from multiple threads.

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


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

Appendix: source

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

      execStatement( "DELETE FROM " + databaseMeta.getQuotedSchemaTableCombination( schema, tablename ) );
    }
  }

  /**
   * Execute a query and return at most one row from the resultset
   *
   * @param sql The SQL for the query
   * @return one Row with data or null if nothing was found.
   */
  public RowMetaAndData getOneRow( String sql ) throws KettleDatabaseException {
    ResultSet rs = openQuery( sql );
    if ( rs != null ) {
      Object[] row = getRow( rs ); // One row only

      try {
        rs.close();
      } catch ( Exception e ) {
        throw new KettleDatabaseException( "Unable to close resultset", e );
      }

      if ( pstmt != null ) {
        try {
          pstmt.close();
        } catch ( Exception e ) {
          throw new KettleDatabaseException( "Unable to close prepared statement pstmt", e );
        }
        pstmt = null;
      }
      if ( selStmt != null ) {
        try {
          selStmt.close();
        } catch ( Exception e ) {
          throw new KettleDatabaseException( "Unable to close prepared statement sel_stmt", e );
        }
        selStmt = null;
      }

View on GitHub (pinned to f3058517a1)