{"record":{"id":"f1f3cc0fc16153a7","repo":"tursodatabase/turso","slug":"savepoints-are-not-supported-by-turso","errorCode":null,"errorMessage":"Savepoints are not supported by Turso","messagePattern":"Savepoints are not supported by Turso","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Connection.java","lineNumber":187,"sourceCode":"\n  @Override\n  public int getHoldability() throws SQLException {\n    connection.checkOpen();\n    return ResultSet.CLOSE_CURSORS_AT_COMMIT;\n  }\n\n  @Override\n  public void setHoldability(int holdability) throws SQLException {\n    connection.checkOpen();\n    if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {\n      throw new SQLException(\"turso only supports CLOSE_CURSORS_AT_COMMIT\");\n    }\n  }\n\n  @Override\n  @SkipNullableCheck\n  public Savepoint setSavepoint() throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");\n  }\n\n  @Override\n  @SkipNullableCheck\n  public Savepoint setSavepoint(String name) throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");\n  }\n\n  @Override\n  public void rollback(Savepoint savepoint) throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");\n  }\n\n  @Override\n  public void releaseSavepoint(Savepoint savepoint) throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");\n  }\n","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Connection.java#L169-L205","documentation":"Connection.setSavepoint() is unconditionally unsupported: turso (like SQLite) has no savepoint/nested-transaction concept exposed through this driver, so JDBC4Connection.java:187 throws SQLFeatureNotSupportedException. Savepoints are the JDBC mechanism for partial rollback inside a transaction, and their absence means every transaction is all-or-nothing. This is a SQLException subclass, so generic catch (SQLException) handlers will intercept it.","triggerScenarios":"Direct calls to connection.setSavepoint(); Spring's PROPAGATION_NESTED @Transactional (DataSourceTransactionManager creates JDBC savepoints for nested transactions); batch frameworks that checkpoint work with savepoints; transaction template code ported from PostgreSQL/SQL Server.","commonSituations":"Spring apps using propagation = Propagation.NESTED; generic DAO frameworks (e.g., older iBATIS/JTA-style code) that call setSavepoint when a transaction is active; migration from drivers where savepoints worked; unit-test infrastructure that verifies rollback behavior via savepoints.","solutions":["Remove savepoint usage and restructure logic so each transaction is atomic - do validation before BEGIN or split into separate transactions.","In Spring, replace Propagation.NESTED with Propagation.REQUIRED or REQUIRES_NEW (a separate physical transaction).","If a third-party library calls setSavepoint, wrap the connection or catch SQLFeatureNotSupportedException and disable that library's savepoint mode.","For retryable sub-work, track applied changes in application state and compensate manually instead of rolling back to a savepoint."],"exampleFix":"// before\nSavepoint sp = conn.setSavepoint();\ntry { riskyWork(conn); }\ncatch (Exception e) { conn.rollback(sp); }\n\n// after\n// turso has no savepoints: verify first, keep the transaction atomic\nif (!preconditionsOk()) { throw new IllegalArgumentException(\"...\"); }\ntry { conn.setAutoCommit(false); riskyWork(conn); conn.commit(); }\ncatch (Exception e) { conn.rollback(); }","handlingStrategy":"try-catch","validationCode":"// capability check: turso does not support savepoints\n// verify driver/database up front and branch your transaction strategy\nboolean supportsSavepoints = false; // for turso\nif (!supportsSavepoints) { /* use plain transactions */ }","typeGuard":null,"tryCatchPattern":"try {\n    Savepoint sp = conn.setSavepoint();\n} catch (SQLFeatureNotSupportedException e) {\n    // savepoints unsupported: fall back to full transaction rollback\n}","preventionTips":["Avoid Spring Propagation.NESTED with turso - it requires JDBC savepoints.","Design transactions as all-or-nothing units; validate before BEGIN.","Do not port savepoint-based partial rollback from other databases.","Grep migrated code for setSavepoint before switching drivers."],"tags":["java","jdbc","turso","transactions","savepoints"],"backgroundTag":"savepoints-not-supported","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}