apache/iceberg · critical · UncheckedSQLException

Failed to connect: %s

Error message

Failed to connect: %s

What it means

Thrown when the JDBC catalog's connection pool cannot open a new JDBC connection to the backing database. DriverManager.getConnection is wrapped so any SQLException becomes an UncheckedSQLException carrying the database URL. It indicates the catalog cannot reach or authenticate against its metadata store.

Source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcClientPool.java:90

    retryableStatusCodes.addAll(COMMON_RETRYABLE_CONNECTION_SQL_STATES);
    String configuredRetryableStatuses = props.get(JdbcUtil.RETRYABLE_STATUS_CODES);
    if (configuredRetryableStatuses != null) {
      retryableStatusCodes.addAll(
          Arrays.stream(configuredRetryableStatuses.split(","))
              .map(status -> status.replaceAll("\\s+", ""))
              .collect(Collectors.toSet()));
    }

    this.dbUrl = dbUrl;
  }

  @Override
  protected Connection newClient() {
    try {
      Properties dbProps = JdbcUtil.filterAndRemovePrefix(properties, JdbcCatalog.PROPERTY_PREFIX);
      return DriverManager.getConnection(dbUrl, dbProps);
    } catch (SQLException e) {
      throw new UncheckedSQLException(e, "Failed to connect: %s", dbUrl);
    }
  }

  @Override
  protected Connection reconnect(Connection client) {
    close(client);
    return newClient();
  }

  @Override
  protected void close(Connection client) {
    try {
      client.close();
    } catch (SQLException e) {
      throw new UncheckedSQLException(e, "Failed to close connection");
    }
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Verify the URI catalog property points to a reachable database (test with a plain JDBC client or ping).
  2. Confirm the JDBC driver jar is on the runtime classpath for the configured URL scheme.
  3. Check username/password and any ssl properties passed via catalog properties are correct.
  4. Confirm the database server is running and accepting connections (connection limits, firewall).
  5. Increase DriverManager login timeout or pool init settings if timeouts are the cause.

Example fix

// before
Map<String, String> props = Map.of("uri", "jdbc:postgresql://wrong-host:5432/iceberg");
JdbcCatalog catalog = new JdbcCatalog();
catalog.setConf(conf); catalog.initialize("jdbc", props);
// after
Map<String, String> props = Map.of(
  "uri", "jdbc:postgresql://db-host:5432/iceberg",
  "jdbc.user", "iceberg",
  "jdbc.password", "secret",
  "driver", "org.postgresql.Driver");
Defensive patterns

Strategy: try-catch

Validate before calling

// verify connectivity before initializing the catalog
try (var conn = java.sql.DriverManager.getConnection(dbUrl, dbProps)) {
  // connection OK
} catch (java.sql.SQLException e) {
  throw new IllegalStateException("Catalog DB unreachable: " + e.getMessage(), e);
}

Try / catch

try {
  catalog.initialize("jdbc", props);
} catch (UncheckedSQLException e) {
  if (e.getCause() instanceof java.sql.SQLException sql && "08001".equals(sql.getSQLState())) {
    // handle unreachable DB: alert / retry with backoff
  }
  throw e;
}

Prevention

When it happens

Trigger: JdbcClientPool.newClient() fails when DriverManager.getConnection(dbUrl, dbProps) throws SQLException, typically on pool cold start or after all pooled connections were invalidated during reconnect.

Common situations: Wrong JDBC URL or hostname, database down or unreachable (network/firewall), bad credentials in catalog properties, missing JDBC driver on classpath, SSL misconfiguration, connection limit exhausted on the DB server.

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/341a082bf9c1c0d7. Report an issue: GitHub.