tursodatabase/turso · error · SQLException
database connection closed
Error message
database connection closed
What it means
SQLException thrown by TursoConnection.checkOpen() when a JDBC method is invoked on a connection whose close() has already completed (the closed flag is set). Every state-touching method — prepare, commit, rollback, setAutoCommit, getAutoCommit, setTransactionIsolation, getTransactionIsolation — calls checkOpen() first, matching standard JDBC 'connection closed' behavior.
Source
Thrown at bindings/java/src/main/java/tech/turso/core/TursoConnection.java:64
* Creates a connection using an existing TursoDB instance. This is useful for encrypted databases
* created with TursoDB.createWithEncryption().
*
* @param url e.g. "jdbc:turso:fileName"
* @param database an existing TursoDB instance
*/
public TursoConnection(String url, TursoDB database) throws SQLException {
this.url = url;
this.database = database;
this.connectionPtr = this.database.connect();
}
private static TursoDB open(String url, String filePath, Properties properties)
throws SQLException {
return TursoDB.create(url, filePath);
}
public void checkOpen() throws SQLException {
if (isClosed()) throw new SQLException("database connection closed");
}
public String getUrl() {
return url;
}
public void close() throws SQLException {
if (isClosed()) {
return;
}
// Roll back any pending transaction before closing
synchronized (transactionLock) {
if (inTransaction) {
try {
executeInternal("ROLLBACK");
} catch (SQLException e) {
// Log but don't throw - we're closing anywayView on GitHub (pinned to bad083fafb)
Solutions
- Check conn.isClosed() before use and reopen or re-borrow from the pool when true
- Scope connections with try-with-resources so close() happens after the last use
- Fix pool configuration (test-on-borrow, sane eviction) so connections are not closed underneath active users
Example fix
// before
try (Connection conn = DriverManager.getConnection(url)) {
doWork(conn);
}
conn.prepareStatement(sql); // SQLException: database connection closed
// after
try (Connection conn = DriverManager.getConnection(url)) {
doWork(conn);
conn.prepareStatement(sql); // still inside the resource scope
} Defensive patterns
Strategy: validation
Validate before calling
if (conn.isClosed()) {
conn = DriverManager.getConnection(url, props); // or re-borrow from the pool
}
try (var ps = conn.prepareStatement(sql)) {
ps.execute();
} Type guard
static boolean isUsable(java.sql.Connection c) throws SQLException {
return c != null && !c.isClosed();
} Try / catch
try {
doWork(conn);
} catch (SQLException e) {
if ("database connection closed".equals(e.getMessage())) {
conn = DriverManager.getConnection(url, props); // reopen / re-borrow
doWork(conn);
} else throw e;
} Prevention
- Scope connections with try-with-resources exactly around their use, not wider
- Never share a single connection across threads without a pool mediating access
- Enable test-on-borrow validation in your connection pool so closed connections never reach callers
When it happens
Trigger: conn.prepareStatement(...) after conn.close(); using a connection outside its try-with-resources block; a connection pool handing out a connection that another thread or an eviction policy already closed.
Common situations: Cleanup code closing early while a background job still uses the connection; pool eviction racing active borrowers; test fixtures closing a shared connection in @AfterAll while later suites reuse it; wrappers that close on error paths but continue processing.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- Failed to convert ${sql} into bytes
- SQLite only supports TYPE_FORWARD_ONLY cursors
- SQLite only supports CONCUR_READ_ONLY cursors
- SQLite only supports closing cursors at commit
- Cannot commit in autocommit mode.
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/708bbfc8867597cc.
Report an issue: GitHub.