apache/shardingsphere · error · SQLFeatureNotSupportedException
releaseSavepoint
Error message
releaseSavepoint
What it means
On a circuit-broken ShardingSphere data source, releaseSavepoint(Savepoint) throws SQLFeatureNotSupportedException because no savepoint could ever have been created (setSavepoint also throws), so releasing one indicates application logic still running against the dead-connection stub. commit()/rollback() are silent no-ops in this state, making releaseSavepoint one of the few visible failures.
Source
Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java:124
@Override
public void rollback(final Savepoint savepoint) throws SQLException {
throw new SQLFeatureNotSupportedException("rollback savepoint");
}
@Override
public Savepoint setSavepoint() throws SQLException {
throw new SQLFeatureNotSupportedException("setSavepoint");
}
@Override
public Savepoint setSavepoint(final String name) throws SQLException {
throw new SQLFeatureNotSupportedException("setSavepoint name");
}
@Override
public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
throw new SQLFeatureNotSupportedException("releaseSavepoint");
}
@Override
public void setHoldability(final int holdability) {
}
@Override
public int getHoldability() {
return 0;
}
@Override
public PreparedStatement prepareStatement(final String sql) {
return new CircuitBreakerPreparedStatement();
}
@Override
public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) {View on GitHub (pinned to e952770a21)
Solutions
- Only release a savepoint if creation actually succeeded (null-check the Savepoint produced by the same live connection).
- Recover the underlying database / close the circuit so genuine connections are returned.
- Wrap releaseSavepoint in try/catch for SQLFeatureNotSupportedException during degraded-mode operation.
- Drop savepoint-based checkpointing for code that must keep running through circuit-break events.
Example fix
// before
finally {
conn.releaseSavepoint(sp);
}
// after
Savepoint sp = null;
try {
sp = supportsSavepoints ? conn.setSavepoint() : null;
...
} finally {
if (null != sp) {
try { conn.releaseSavepoint(sp); } catch (final SQLFeatureNotSupportedException ignored) { }
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if (null != sp) {
try { conn.releaseSavepoint(sp); } catch (final SQLFeatureNotSupportedException ignored) { }
} Try / catch
finally {
if (null != sp) {
try {
conn.releaseSavepoint(sp);
} catch (final SQLFeatureNotSupportedException ex) {
LOGGER.debug("savepoint release skipped: {}", ex.getMessage());
}
}
} Prevention
- Only release savepoints created by the same, still-healthy connection.
- Keep cleanup code exception-tolerant during degraded/circuit-broken states.
- Never cache Savepoint objects across connection failures.
When it happens
Trigger: Calling conn.releaseSavepoint(sp) — usually in a finally block after setSavepoint previously threw, or with a Savepoint object held from before the circuit opened — on a CircuitBreakerConnection.
Common situations: finally { if (sp != null) conn.releaseSavepoint(sp); } cleanup code executing during an outage; transaction-template code that releases checkpoints even when creation failed; failover tests that keep using stale Connection objects.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/715852e1c6e903e3.
Report an issue: GitHub.