apache/iceberg · error · UncheckedSQLException

Unknown failure

Error message

Unknown failure

What it means

A generic fallback in JdbcTableOperations.doCommit: any SQLException that is not a timeout, connection failure, data truncation, SQLWarning, or unique-constraint violation is wrapped in UncheckedSQLException with the uninformative message 'Unknown failure'. It means the underlying JDBC driver reported an error the catalog did not classify; the root cause is in the chained SQLException.

Source

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

    } 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");
    }
  }

  private void updateTable(String newMetadataLocation, String oldMetadataLocation)
      throws SQLException, InterruptedException {
    int updatedRecords =
        JdbcUtil.updateTable(
            schemaVersion,
            connections,
            catalogName,
            tableIdentifier,
            newMetadataLocation,
            oldMetadataLocation);

    if (updatedRecords == 1) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Inspect the chained cause: getCause().getSQLException() / print the full stack to see the real SQL error and vendor code
  2. Initialize the JDBC catalog schema (tables jdbc_tables, jdbc_namespaces, etc.) in the target database
  3. Grant the catalog DB user SELECT/INSERT/UPDATE on the catalog tables
  4. If deadlocks are the cause, retry the commit (CommitState/RetryUtil) or reduce commit concurrency

Example fix

// before
} catch (UncheckedSQLException e) {
  LOG.error("commit failed");
}
// after
} catch (UncheckedSQLException e) {
  LOG.error("commit failed", e.getCause()); // chained SQLException reveals real vendor error
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify catalog DB is initialized and reachable before committing
assert catalog.tableExists(identifier) || catalog.namespaceExists(identifier.namespace());

Try / catch

try { commit(); } catch (UncheckedSQLException e) { SQLException sql = (SQLException) e.getCause(); LOG.error("SQL state={} vendorCode={}", sql.getSQLState(), sql.getErrorCode(), sql); }

Prevention

When it happens

Trigger: Any SQL error during loadTable/updateTable/insert that falls outside the caught categories: syntax errors, missing jdbc_tables catalog table, permissions denied, deadlock victims, disk-full on the metadata DB, driver-specific error codes not matching isConstraintViolation.

Common situations: Catalog database not initialized (missing jdbc_tables/jdbc_namespaces tables after upgrading or pointing at a fresh DB); DB user lacking INSERT/UPDATE grants; Postgres/MySQL deadlock under concurrent commits; unsupported SQL dialect.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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