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
- Read the chained SQLException cause for the real database error and fix that underlying issue
- Verify JDBC URL, credentials, and that the database is reachable (test connection)
- Ensure catalog tables are initialized (initializeCatalogTables) and the user has DML grants
- 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
- Always inspect the chained SQLException cause
- Use a connection pool with health checks (validation queries)
- Grant the catalog user INSERT/UPDATE/DELETE on catalog tables
- Keep long transactions short to avoid lock timeouts
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
- Cannot initialize JDBC catalog
- Cannot check and eventually update SQL schema
- Failed to execute query: %s
- Failed to get table %s from catalog %s
- Failed to execute exists query: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/b77174d04885c52a.
Report an issue: GitHub.