{"record":{"id":"4f880e0a5e354494","repo":"tursodatabase/turso","slug":"cannot-change-isolation-level-while-transaction-is","errorCode":null,"errorMessage":"Cannot change isolation level while transaction is active.","messagePattern":"Cannot change isolation level while transaction is active\\.","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"bindings/java/src/main/java/tech/turso/core/TursoConnection.java","lineNumber":294,"sourceCode":"    }\n  }\n\n  /**\n   * Sets the transaction isolation level.\n   *\n   * @param level one of the following {@code Connection} constants: {@code\n   *     Connection.TRANSACTION_READ_UNCOMMITTED}, {@code Connection.TRANSACTION_READ_COMMITTED},\n   *     {@code Connection.TRANSACTION_REPEATABLE_READ}, or {@code\n   *     Connection.TRANSACTION_SERIALIZABLE}.\n   * @throws SQLException if a database access error occurs, this method is called on a closed\n   *     connection or the given parameter is not one of the {@code Connection} constants\n   */\n  public void setTransactionIsolation(int level) throws SQLException {\n    synchronized (transactionLock) {\n      checkOpen();\n\n      if (inTransaction) {\n        throw new SQLException(\"Cannot change isolation level while transaction is active.\");\n      }\n\n      if (level != Connection.TRANSACTION_READ_UNCOMMITTED\n          && level != Connection.TRANSACTION_READ_COMMITTED\n          && level != Connection.TRANSACTION_REPEATABLE_READ\n          && level != Connection.TRANSACTION_SERIALIZABLE) {\n        throw new SQLException(\"Invalid transaction isolation level: \" + level);\n      }\n\n      this.transactionIsolation = level;\n    }\n  }\n\n  /**\n   * Retrieves the current transaction isolation level.\n   *\n   * @return the current transaction isolation level\n   * @throws SQLException if a database access error occurs or the connection is closed","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/core/TursoConnection.java#L276-L312","documentation":"TursoConnection.setTransactionIsolation() rejects the call while inTransaction is true. Turso starts transactions lazily — once autocommit is off, executing any non-control statement begins a transaction implicitly — so the connection can be inside one even without an explicit BEGIN.","triggerScenarios":"Disabling autocommit, executing any statement (implicit BEGIN via the lazy transaction starter), then calling setTransactionIsolation(...) before commit()/rollback() completes the transaction.","commonSituations":"Connection-pool code that resets isolation on borrow/return while a user's transaction is still active; Spring's DataSourceUtils adjusting isolation per transaction definition; long-lived connections reused across test methods without cleanup.","solutions":["Commit or roll back the active transaction first: if (!conn.getAutoCommit()) { conn.commit(); }","Set the isolation level once immediately after obtaining the connection, before executing any statement","In pool interceptors, only touch isolation after verifying the connection is idle (no lazy transaction open)"],"exampleFix":"// before\nconn.setAutoCommit(false);\ntry (Statement st = conn.createStatement()) { st.execute(\"SELECT 1\"); }\nconn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // throws\n\n// after\nif (!conn.getAutoCommit()) conn.commit();   // end the lazy transaction\nconn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);","handlingStrategy":"validation","validationCode":"if (!conn.getAutoCommit()) {\n  conn.commit();   // end any lazily-started transaction first\n}\nconn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);","typeGuard":null,"tryCatchPattern":"try {\n  conn.setTransactionIsolation(level);\n} catch (SQLException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"transaction is active\")) {\n    conn.commit();\n    conn.setTransactionIsolation(level); // retry on a quiescent connection\n  } else {\n    throw e;\n  }\n}","preventionTips":["Set isolation once, immediately after obtaining a connection, before executing any statement","Remember Turso begins transactions lazily — any executed statement can open one without BEGIN","In pool interceptors, only adjust isolation on connections verified idle (borrow boundary), never mid-use"],"tags":["java","jdbc","transaction","isolation","bindings"],"backgroundTag":"isolation-change-during-active-transaction","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}