apache/shardingsphere · error · SQLFeatureNotSupportedException
first
Error message
first
What it means
first() moves the cursor to row 1 and reports success; ShardingSphere's forward-only merged ResultSet cannot jump backward to the first row, so the method is final and throws SQLFeatureNotSupportedException. Row 1 may already have been consumed from the shard merge stream.
Source
Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java:70
@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");
}
@Override
public final boolean first() throws SQLException {
throw new SQLFeatureNotSupportedException("first");
}
@Override
public final boolean last() throws SQLException {
throw new SQLFeatureNotSupportedException("last");
}
@Override
public final boolean absolute(final int row) throws SQLException {
throw new SQLFeatureNotSupportedException("absolute");
}
@Override
public final boolean relative(final int rows) throws SQLException {
throw new SQLFeatureNotSupportedException("relative");
}
@OverrideView on GitHub (pinned to e952770a21)
Solutions
- Use rs.next() to position on the first row — it is the supported forward move and returns false when empty.
- For guaranteed-single-row queries, still check next() and optionally assert !rs.next() again.
- If you need random access later, copy rows into a List while iterating.
- Configure tools that call first() (report engines, mappers) to use next()-based iteration or give them a CachedRowSet.
Example fix
// before
if (rs.first()) { name = rs.getString(1); } // throws
// after
if (rs.next()) { name = rs.getString(1); } Defensive patterns
Strategy: validation
Validate before calling
if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {
boolean hasRow = rs.next(); // use next() instead of first()
} Try / catch
try {
if (rs.first()) { read(rs); }
} catch (SQLFeatureNotSupportedException e) {
if (rs.next()) { read(rs); }
} Prevention
- Write single-row reads with next(), the universally supported forward move.
- In shared helpers, expose only next()-based accessors.
- Watch for first()/last() in code migrated from Oracle-style tutorials.
When it happens
Trigger: Calling rs.first() — e.g. to fetch a single expected row — on a ResultSet from ShardingSphereDataSource instead of next().
Common situations: Single-row lookups written as if (rs.first()) { ... }; code migrated from Oracle/DB2 style; generic DAO helpers that call first() before reading columns.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/4a9976499daf5932.
Report an issue: GitHub.