prestodb/presto · error · SQLFeatureNotSupportedException
Result set type must be TYPE_FORWARD_ONLY
Error message
Result set type must be TYPE_FORWARD_ONLY
What it means
PrestoConnection.checkResultSet() throws SQLFeatureNotSupportedException when createStatement/prepareStatement is called with a resultSetType other than ResultSet.TYPE_FORWARD_ONLY. Presto query results are streamed over HTTP in one direction, so scrollable (TYPE_SCROLL_INSENSITIVE/TYPE_SCROLL_SENSITIVE) result sets are genuinely unsupported, not just unimplemented. The check runs before any statement is created.
Source
Thrown at presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoConnection.java:894
throws SQLException
{
if (isClosed()) {
throw new SQLException("Connection is closed");
}
}
private void initializeQueryInterceptors()
{
for (QueryInterceptor interceptor : this.queryInterceptorInstances) {
interceptor.init(this.sessionProperties);
}
}
private static void checkResultSet(int resultSetType, int resultSetConcurrency)
throws SQLFeatureNotSupportedException
{
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY) {
throw new SQLFeatureNotSupportedException("Result set type must be TYPE_FORWARD_ONLY");
}
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw new SQLFeatureNotSupportedException("Result set concurrency must be CONCUR_READ_ONLY");
}
}
private static void checkHoldability(int resultSetHoldability)
throws SQLFeatureNotSupportedException
{
if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
throw new SQLFeatureNotSupportedException("Result set holdability must be HOLD_CURSORS_OVER_COMMIT");
}
}
private static String getIsolationLevel(int level)
throws SQLException
{
switch (level) {View on GitHub (pinned to 55bb57d202)
Solutions
- Use createStatement() / prepareStatement(sql) with defaults (TYPE_FORWARD_ONLY, CONCUR_READ_ONLY)
- Explicitly pass ResultSet.TYPE_FORWARD_ONLY and ResultSet.CONCUR_READ_ONLY
- If random access is needed, buffer rows into your own list instead of scrolling the ResultSet
Example fix
// before
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
// after
Statement stmt = conn.createStatement(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); Defensive patterns
Strategy: validation
Validate before calling
int type = ResultSet.TYPE_SCROLL_INSENSITIVE; // value read from config
if (type != ResultSet.TYPE_FORWARD_ONLY) {
type = ResultSet.TYPE_FORWARD_ONLY; // coerce before calling driver
} Try / catch
try {
stmt = conn.createStatement(type, ResultSet.CONCUR_READ_ONLY);
} catch (SQLFeatureNotSupportedException e) {
stmt = conn.createStatement(); // fallback to defaults
} Prevention
- Always use the no-arg createStatement()/prepareStatement(sql) with Presto
- Centralize statement creation in one helper that pins forward-only/read-only
- Do not port scrollable-cursor settings from other JDBC drivers
When it happens
Trigger: createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ...), createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ...), prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ...) or any call passing a non-forward-only type.
Common situations: Shared DAO/utility code written for MySQL/Oracle that requests scrollable cursors by default; ORM or reporting frameworks configured with scrollable result sets; copy-pasted connection code from another driver's samples.
Related errors
- Result set concurrency must be CONCUR_READ_ONLY
- Result set holdability must be HOLD_CURSORS_OVER_COMMIT
- privileges not supported
- row identifiers not supported
- version columns not supported
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/cd575b387330345b.
Report an issue: GitHub.