apache/iceberg · error · UncheckedInterruptedException

Interrupted during commit

Error message

Interrupted during commit

What it means

The thread performing a JDBC catalog commit was interrupted while the underlying operation used interruptible connection/transaction helpers (JdbcUtil runs SQL inside Tasks with connection pools that may block). Iceberg re-asserts the interrupt flag and throws UncheckedInterruptedException so callers know the commit did not complete and its outcome is unknown.

Source

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

    } 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) {
      LOG.debug("Successfully committed to existing table: {}", tableIdentifier);
    } else {
      throw new CommitFailedException(

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Let the commit retry after the interrupt: catch UncheckedInterruptedException, restore interrupt status, and re-attempt the commit once the thread pool is healthy
  2. Verify the table's current metadata location after an interrupted commit to determine if it landed (commit may have succeeded before interruption)
  3. Avoid cancelling commit threads abruptly; use catalog-level commit timeouts/retries instead
  4. Ensure HikariCP/pool shutdown hooks don't interrupt in-flight connections during orderly shutdown

Example fix

// before
executor.shutdownNow(); // may interrupt in-flight commits
// after
executor.shutdown();
executor.awaitTermination(5, TimeUnit.MINUTES); // let commits drain before forcing interrupt
Defensive patterns

Strategy: try-catch

Validate before calling

if (Thread.currentThread().isInterrupted()) { /* defer or abort commit before starting */ }

Try / catch

try { table.newAppend().appendFile(f).commit(); } catch (UncheckedInterruptedException e) { Thread.currentThread().interrupt(); /* verify current metadata location, then retry if not landed */ }

Prevention

When it happens

Trigger: Executor shutdown / application teardown while a commit is in flight; Future.cancel(true) on a task running catalog.commit(); thread-pool rejection paths; query timeouts implemented via cancellation in the connection pool (e.g. HikariCP connection interruption).

Common situations: Spark job cancelled mid-commit; Flink checkpoint/commit thread interrupted at shutdown; test framework timeouts interrupting commit threads; Kubernetes pod terminating during commit.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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