apache/iceberg · error · UncheckedSQLException

Failed to execute: %s

Error message

Failed to execute: %s

What it means

The catalog's execute() helper wraps SQL updates in Tasks; when executeUpdate throws a SQLException that the configured sqlErrorHandler does not consume (convert) into a typed Iceberg exception, it is rethrown as UncheckedSQLException with "Failed to execute: %s". It indicates the DML statement (insert/update/delete of catalog metadata) failed at the database level.

Source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java:780

  private int execute(String sql, String... args) {
    return execute(err -> {}, sql, args);
  }

  private int execute(Consumer<SQLException> sqlErrorHandler, String sql, String... args) {
    try {
      return connections.run(
          conn -> {
            try (PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
              for (int pos = 0; pos < args.length; pos += 1) {
                preparedStatement.setString(pos + 1, args[pos]);
              }

              return preparedStatement.executeUpdate();
            }
          });
    } catch (SQLException e) {
      sqlErrorHandler.accept(e);
      throw new UncheckedSQLException(e, "Failed to execute: %s", sql);
    } catch (InterruptedException e) {
      throw new UncheckedInterruptedException(e, "Interrupted in SQL command");
    }
  }

  @FunctionalInterface
  interface RowProducer<R> {
    R apply(ResultSet result) throws SQLException;
  }

  @SuppressWarnings("checkstyle:NestedTryDepth")
  private <R> List<R> fetch(RowProducer<R> toRow, String sql, String... args) {
    try {
      return connections.run(
          conn -> {
            List<R> result = Lists.newArrayList();

            try (PreparedStatement preparedStatement = conn.prepareStatement(sql)) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Read the chained SQLException cause for the real database error and fix that underlying issue
  2. Verify JDBC URL, credentials, and that the database is reachable (test connection)
  3. Ensure catalog tables are initialized (initializeCatalogTables) and the user has DML grants
  4. Retry transient failures (locks, deadlocks) and check for long-running transactions holding locks

Example fix

// before
catalog.createNamespace(ns);
// after
try {
  catalog.createNamespace(ns);
} catch (UncheckedSQLException e) {
  LOG.error("SQL failed: {}", e.getCause().getMessage());
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify connectivity before catalog writes
try (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) {
  if (!c.isValid(5)) throw new IllegalStateException("DB unreachable");
}

Try / catch

try {
  catalog.createNamespace(ns);
} catch (UncheckedSQLException e) {
  Throwable cause = e.getCause();
  LOG.error("Catalog SQL write failed: {}", cause.getMessage(), cause);
  if (cause.getMessage().contains("connection")) { /* retry path */ }
  throw e;
}

Prevention

When it happens

Trigger: Any JdbcCatalog metadata write (create/drop/rename table or view, namespace and property updates) whose prepared statement raises a SQLException not classified as a constraint violation by the error handler: connectivity loss, syntax errors, schema mismatch, lock timeouts, permission denial.

Common situations: Database restarted or connection pool exhausted; wrong JDBC URL/credentials; missing table (catalog tables not initialized); DB user lacking INSERT/UPDATE/DELETE grants; deadlocks or lock wait timeouts under concurrent commits.

Related errors


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