apache/shardingsphere · error · ResultSetClosedException

2

2

Error message

Result set has been closed.

What it means

ResultSetClosedException (code 2) thrown by DatabaseMetaDataResultSet.checkClosed when any accessor is invoked after the metadata result set was closed. ShardingSphere explicitly guards closed state because this result set is a self-contained object over cached metadata rows.

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/core/resultset/DatabaseMetaDataResultSet.java:422

    
    @Override
    public int getFetchSize() throws SQLException {
        return resultSet.getFetchSize();
    }
    
    @Override
    public void setFetchSize(final int rows) throws SQLException {
        resultSet.setFetchSize(rows);
    }
    
    @Override
    public boolean isClosed() {
        return closed;
    }
    
    private void checkClosed() throws SQLException {
        if (closed) {
            throw new ResultSetClosedException().toSQLException();
        }
    }
    
    private void checkColumnIndex(final int columnIndex) throws SQLException {
        if (columnIndex < 1 || columnIndex > resultSetMetaData.getColumnCount()) {
            throw new ColumnIndexOutOfRangeException(columnIndex).toSQLException();
        }
    }
    
    @EqualsAndHashCode
    private static final class DatabaseMetaDataObject {
        
        private final List<Object> objects;
        
        private DatabaseMetaDataObject(final int columnCount) {
            objects = new ArrayList<>(columnCount);
        }
        

View on GitHub (pinned to e952770a21)

Solutions

  1. Copy the needed rows out of the metadata ResultSet (into a list/DTO) before leaving the try-with-resources block.
  2. Ensure only the owner that opened the ResultSet closes it, and never access it afterwards.
  3. Remove duplicate close() calls or overly broad try-with-resources scoping.

Example fix

// before
try (ResultSet rs = meta.getTables(null, null, "%", null)) { tables = rs; }
String s = tables.getString(1); // closed
// after
try (ResultSet rs = meta.getTables(null, null, "%", null)) {
    while (rs.next()) { names.add(rs.getString("TABLE_NAME")); }
}
Defensive patterns

Strategy: validation

Validate before calling

if (rs.isClosed()) throw new IllegalStateException("result set already closed");

Try / catch

catch (SQLException ex) { if (rs != null && rs.isClosed()) reopenOrRefetch(); else throw ex; }

Prevention

When it happens

Trigger: Calling any method guarded by checkClosed() (findColumn, getType, getConcurrency, getters, etc.) on a DatabaseMetaData ResultSet after close() was called — often implicitly by frameworks or try-with-resources scoping.

Common situations: Using a metadata ResultSet after the enclosing try block closed it; caching a ResultSet beyond its scope; double iteration where the first loop closes; helper utilities that close result sets eagerly.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/82a12672df53d079. Report an issue: GitHub.