tursodatabase/turso · error · SQLException
Invalid transaction isolation level
Error message
Invalid transaction isolation level: {level} What it means
Thrown by TursoConnection.setTransactionIsolation(int) when level is not one of the four accepted JDBC constants: TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ, or TRANSACTION_SERIALIZABLE. The setter stores the level verbatim, so it validates the full domain up front under the transaction lock. Note that TRANSACTION_NONE (0), a standard JDBC constant, is rejected because the engine cannot disable isolation.
Solutions
- Pass exactly one of the four Connection constants listed in the check
- If you meant TRANSACTION_NONE, remove the call entirely: the engine has no dirty reads and the connection default is already fine
- Map free-form config strings/values to the four constants through an allowlist before calling the setter
- As a last resort, wrap the call in try-catch and fall back to the value returned by getTransactionIsolation()
Example fix
// before conn.setTransactionIsolation(Connection.TRANSACTION_NONE); // throws // after // TRANSACTION_NONE is not supported; only these four are accepted conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Defensive patterns
Strategy: validation
Validate before calling
private static final Set<Integer> SUPPORTED_ISOLATION = Set.of(
Connection.TRANSACTION_READ_UNCOMMITTED,
Connection.TRANSACTION_READ_COMMITTED,
Connection.TRANSACTION_REPEATABLE_READ,
Connection.TRANSACTION_SERIALIZABLE);
if (!SUPPORTED_ISOLATION.contains(level)) {
throw new IllegalArgumentException(
"level must be one of the four JDBC isolation constants, got: " + level);
}
conn.setTransactionIsolation(level); Try / catch
try {
conn.setTransactionIsolation(level);
} catch (SQLException e) {
// keep the current level; surface a clear config error instead of a generic SQLException
throw new ConfigurationException("unsupported isolation level: " + level, e);
} Prevention
- Map pool/config strings to the four constants through one allowlist function
- Set isolation once at connection setup, never inside an active transaction
- Unit-test every configurable level value against the allowlist
When it happens
Trigger: Calling conn.setTransactionIsolation(level) with Connection.TRANSACTION_NONE, an arbitrary int (e.g. 5 or -1), or a value read from configuration that is not exactly one of the four accepted constants. Calling it while a transaction is active throws a different message first ('Cannot change isolation level while transaction is active.').
Common situations: Ported JDBC code that defaults to TRANSACTION_NONE; passing a connection-pool property (e.g. HikariCP's transactionIsolation) straight through as an int; constants renamed or mistyped after a refactor; code written for PostgreSQL/MySQL where NONE is accepted.
Related errors
- Cannot change isolation level while transaction is active.
- Cannot commit in autocommit mode.
- Cannot rollback in autocommit mode.
- Failed to rollback transaction during close
- Invalid argument
AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20).
Data as JSON: /api/errors/a1ce0edc7f082d58.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoConnection.java:301
* Connection.TRANSACTION_READ_UNCOMMITTED}, {@code Connection.TRANSACTION_READ_COMMITTED},
* {@code Connection.TRANSACTION_REPEATABLE_READ}, or {@code
* Connection.TRANSACTION_SERIALIZABLE}.
* @throws SQLException if a database access error occurs, this method is called on a closed
* connection or the given parameter is not one of the {@code Connection} constants
*/
public void setTransactionIsolation(int level) throws SQLException {
synchronized (transactionLock) {
checkOpen();
if (inTransaction) {
throw new SQLException("Cannot change isolation level while transaction is active.");
}
if (level != Connection.TRANSACTION_READ_UNCOMMITTED
&& level != Connection.TRANSACTION_READ_COMMITTED
&& level != Connection.TRANSACTION_REPEATABLE_READ
&& level != Connection.TRANSACTION_SERIALIZABLE) {
throw new SQLException("Invalid transaction isolation level: " + level);
}
this.transactionIsolation = level;
}
}
/**
* Retrieves the current transaction isolation level.
*
* @return the current transaction isolation level
* @throws SQLException if a database access error occurs or the connection is closed
*/
public int getTransactionIsolation() throws SQLException {
checkOpen();
return transactionIsolation;
}
/**View on GitHub (pinned to 244cde92a7)