apache/shardingsphere · error · SQLFeatureNotSupportedException
isAfterLast
Error message
isAfterLast
What it means
isAfterLast() is unsupported on ShardingSphere result sets: the class makes it final and throws SQLFeatureNotSupportedException. A forward-only streaming merge never exposes an 'after last' position to user code — the iteration simply ends when next() returns false — so the driver forbids the probe.
Source
Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:45
/**
* Unsupported {@code ResultSet} methods.
*/
public abstract class AbstractUnsupportedOperationResultSet extends AbstractUnsupportedUpdateOperationResultSet {
@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");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Use while (rs.next()) as the loop condition; next()==false already means the cursor is past the last row.
- Materialize rows into a List if you need arbitrary position checks afterward.
- For row counts, issue a separate COUNT query or accumulate a counter during iteration.
- Shield third-party callers by handing them a CachedRowSet built from the forward-only result.
Example fix
// before
while (!rs.isAfterLast()) { rs.next(); process(rs); } // throws
// after
while (rs.next()) { process(rs); } Defensive patterns
Strategy: validation
Validate before calling
if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
// terminate loops with rs.next(), not !rs.isAfterLast()
} Try / catch
try {
while (!rs.isAfterLast()) { rs.next(); }
} catch (SQLFeatureNotSupportedException e) {
while (rs.next()) { }
} Prevention
- Always use while (rs.next()) — it is the only supported loop idiom here.
- Reject code-review patterns that call isAfterLast/isBeforeFirst in loop conditions.
- Buffer rows when end-position knowledge is required.
When it happens
Trigger: Calling rs.isAfterLast() on a query result from ShardingSphereDataSource, e.g. loop guards like while (!rs.isAfterLast()) instead of while (rs.next()).
Common situations: Iteration idioms ported from scroll-insensitive cursors; frameworks that verify iteration completion with position predicates; code generated by tools that emit the JDBC tutorial-style position checks.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/ccfb097aeddcc561.
Report an issue: GitHub.