apache/iceberg · error · UncheckedSQLException

Database Connection failed

Error message

Database Connection failed

What it means

Thrown when doCommit fails with SQLTransientConnectionException or SQLNonTransientConnectionException — the database connection failed during the commit. Transient means a retry might succeed; non-transient means a persistent connection problem. The commit did not land.

Source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcTableOperations.java:125

      Map<String, String> table =
          JdbcUtil.loadTable(schemaVersion, connections, catalogName, tableIdentifier);

      if (base != null) {
        validateMetadataLocation(table, base);
        String oldMetadataLocation = base.metadataFileLocation();
        // Start atomic update
        LOG.debug("Committing existing table: {}", tableName());
        updateTable(newMetadataLocation, oldMetadataLocation);
      } else {
        // table not exists create it
        LOG.debug("Committing new table: {}", tableName());
        createTable(newMetadataLocation);
      }

    } catch (SQLTimeoutException e) {
      throw new UncheckedSQLException(e, "Database Connection timeout");
    } catch (SQLTransientConnectionException | SQLNonTransientConnectionException e) {
      throw new UncheckedSQLException(e, "Database Connection failed");
    } catch (DataTruncation e) {
      throw new UncheckedSQLException(e, "Database data truncation error");
    } catch (SQLWarning e) {
      throw new UncheckedSQLException(e, "Database warning");
    } catch (SQLException e) {
      if (JdbcUtil.isConstraintViolation(e)) {
        if (currentMetadataLocation() == null) {
          throw new AlreadyExistsException(e, "Table already exists: %s", tableIdentifier);
        } else {
          throw new UncheckedSQLException(e, "Table already exists: %s", tableIdentifier);
        }
      }

      throw new UncheckedSQLException(e, "Unknown failure");
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new UncheckedInterruptedException(e, "Interrupted during commit");
    }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Retry the commit — Iceberg retries commits and transient connection errors often resolve.
  2. Check database availability, max_connections, and pool sizing.
  3. Increase pool size / connection timeout properties so commits don't starve.
  4. Inspect server logs for failover or crash events coinciding with the commit.

Example fix

// before
Map<String,String> props = Map.of("uri", url); // default pool, exhausted under load
// after
Map<String,String> props = Map.of("uri", url, "pool.maxSize", "20", "jdbc.max-connections", "20");
Defensive patterns

Strategy: retry

Validate before calling

// confirm DB reachable and pool not exhausted before batch commits
try (var conn = java.sql.DriverManager.getConnection(dbUrl, dbProps)) {
  if (!conn.isValid(5)) throw new IllegalStateException("Catalog DB connection invalid");
}

Try / catch

try {
  commit();
} catch (UncheckedSQLException e) {
  Throwable c = e.getCause();
  if (c instanceof java.sql.SQLTransientConnectionException) {
    retryWithBackoff(this::commit); // transient: safe to retry
  } else throw e;
}

Prevention

When it happens

Trigger: doCommit() throws SQLTransientConnectionException or SQLNonTransientConnectionException while executing catalog UPDATE/INSERT — pooled connection lost or cannot be established at commit time.

Common situations: Database restart/failover mid-commit, network blip, pool exhausted and connection acquisition failing, DB max_connections reached, authentication expiry.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/d6c380ef4319be6e. Report an issue: GitHub.