apache/shardingsphere · error · SQLFeatureNotSupportedException
isFirst
Error message
isFirst
What it means
isFirst() — asking whether the cursor is on the first row — is a final, throwing method in ShardingSphere's AbstractUnsupportedOperationResultSet. Forward-only merged results do not maintain row-number state for position introspection, so the call fails with SQLFeatureNotSupportedException.
Source
Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:50
@Override
public final boolean previous() throws SQLException {
throw new SQLFeatureNotSupportedException("previous");
}
@Override
public final boolean isBeforeFirst() throws SQLException {
throw new SQLFeatureNotSupportedException("isBeforeFirst");
}
@Override
public final boolean isAfterLast() throws SQLException {
throw new SQLFeatureNotSupportedException("isAfterLast");
}
@Override
public final boolean isFirst() throws SQLException {
throw new SQLFeatureNotSupportedException("isFirst");
}
@Override
public final boolean isLast() throws SQLException {
throw new SQLFeatureNotSupportedException("isLast");
}
@Override
public final void beforeFirst() throws SQLException {
throw new SQLFeatureNotSupportedException("beforeFirst");
}
@Override
public final void afterLast() throws SQLException {
throw new SQLFeatureNotSupportedException("afterLast");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Track the position yourself with a boolean or row counter updated as you call next().
- Pre-buffer all rows into a List and use index-based checks (i == 0).
- If you must special-case the first row, read it once before entering the loop for the remainder.
- For heavyweight frameworks needing position APIs, feed them a CachedRowSet or RowSetProvider copy.
Example fix
// before
while (rs.next()) { if (rs.isFirst()) writeHeader(); writeRow(rs); } // throws
// after
boolean first = true;
while (rs.next()) { if (first) { writeHeader(); first = false; } writeRow(rs); } Defensive patterns
Strategy: validation
Validate before calling
if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
// track first-row state in a local boolean, never rs.isFirst()
} Try / catch
try {
if (rs.isFirst()) { ... }
} catch (SQLFeatureNotSupportedException e) {
// fall back to your own row counter (row == 1 means first)
} Prevention
- Maintain a local row counter or boolean for first-row special-casing.
- Prefer index-based logic over an in-memory list for position-dependent formatting.
- Static-analysis rule: no ResultSet position getters on forward-only cursors.
When it happens
Trigger: Calling rs.isFirst() inside an iteration loop, e.g. to skip a separator/header only on the first row, on a result set produced via the ShardingSphere driver.
Common situations: CSV/JSON exporters that special-case the first row; pagination logic that branches on cursor position; generic row visitors copied from code written against scrollable result sets.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/12bec183a7cdf22e.
Report an issue: GitHub.