{"record":{"id":"25118ab290095478","repo":"pentaho/pentaho-kettle","slug":"unable-to-close-resultset","errorCode":null,"errorMessage":"Unable to close resultset","messagePattern":"Unable to close resultset","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/database/Database.java","lineNumber":3612,"sourceCode":"      execStatement( \"DELETE FROM \" + databaseMeta.getQuotedSchemaTableCombination( schema, tablename ) );\n    }\n  }\n\n  /**\n   * Execute a query and return at most one row from the resultset\n   *\n   * @param sql The SQL for the query\n   * @return one Row with data or null if nothing was found.\n   */\n  public RowMetaAndData getOneRow( String sql ) throws KettleDatabaseException {\n    ResultSet rs = openQuery( sql );\n    if ( rs != null ) {\n      Object[] row = getRow( rs ); // One row only\n\n      try {\n        rs.close();\n      } catch ( Exception e ) {\n        throw new KettleDatabaseException( \"Unable to close resultset\", e );\n      }\n\n      if ( pstmt != null ) {\n        try {\n          pstmt.close();\n        } catch ( Exception e ) {\n          throw new KettleDatabaseException( \"Unable to close prepared statement pstmt\", e );\n        }\n        pstmt = null;\n      }\n      if ( selStmt != null ) {\n        try {\n          selStmt.close();\n        } catch ( Exception e ) {\n          throw new KettleDatabaseException( \"Unable to close prepared statement sel_stmt\", e );\n        }\n        selStmt = null;\n      }","sourceCodeStart":3594,"sourceCodeEnd":3630,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/database/Database.java#L3594-L3630","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the wrapped cause (KettleDatabaseException.getCause()) to see the real SQLException and fix the underlying connection/driver issue","Ensure the Database connection is open and healthy before calling getOneRow; reconnect with db.connect() if disconnect() was called or the connection timed out","Upgrade the JDBC driver for the target database to a current version","Avoid sharing a single Database instance across threads; use one instance per thread/execution"],"exampleFix":"// before\nRowMetaAndData r = database.getOneRow( \"SELECT COUNT(*) FROM t\" ); // may throw on close\n// after\nRowMetaAndData r = null;\ntry {\n  r = database.getOneRow( \"SELECT COUNT(*) FROM t\" );\n} catch ( KettleDatabaseException e ) {\n  logError( \"Failed to fetch/close: \" + e.getCause(), e );\n  database.disconnect();\n  database.connect();\n  r = database.getOneRow( \"SELECT COUNT(*) FROM t\" );\n}","handlingStrategy":"try-catch","validationCode":"if ( database == null || !isConnected( database ) ) {\n  throw new IllegalStateException( \"Database connection is not open; call connect() before getOneRow()\" );\n}","typeGuard":"boolean isUsable( Database db ) {\n  return db != null && db.getConnection() != null; // non-null open JDBC connection\n}","tryCatchPattern":"try {\n  RowMetaAndData row = database.getOneRow( sql );\n} catch ( KettleDatabaseException e ) {\n  Throwable cause = e.getCause();\n  log.logError( \"getOneRow cleanup failed: \" + ( cause != null ? cause.getMessage() : e.getMessage() ), e );\n  database.disconnect();\n  database.connect();\n  // retry once or degrade gracefully\n}","preventionTips":["Always verify the connection is open before querying; reconnect after idle periods","Read e.getCause() — the real SQLException explains whether close or the connection failed","Use one Database instance per thread to avoid concurrent close races","Keep JDBC drivers up to date; old drivers often throw on closing exhausted resultsets"],"tags":["database","jdbc","resultset","resource-cleanup"],"backgroundTag":"database-query-failed","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}