apache/iceberg · info · UncheckedInterruptedException

Interrupted during isHeld

Error message

Interrupted during isHeld

What it means

Thrown by JdbcLock.isHeld when the thread is interrupted while querying the lock table to determine whether the lock is still held. The interrupt flag is restored and the InterruptedException is wrapped in UncheckedInterruptedException. No lock state was determined.

Source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java:227

    }

    @SuppressWarnings("checkstyle:NestedTryDepth")
    @Override
    public boolean isHeld() {
      try {
        return pool.run(
            conn -> {
              try (PreparedStatement sql = conn.prepareStatement(GET_LOCK_SQL)) {
                sql.setString(1, type.key);
                sql.setString(2, lockId);
                try (ResultSet rs = sql.executeQuery()) {
                  return rs.next();
                }
              }
            });
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new UncheckedInterruptedException(e, "Interrupted during isHeld");
      } catch (SQLException e) {
        // SQL exception happened when getting lock information
        throw new UncheckedSQLException(e, "Failed to check the state of the lock %s", this);
      }
    }

    @SuppressWarnings("checkstyle:NestedTryDepth")
    @Override
    public void unlock() {
      try {
        // Possible concurrency issue:
        // - `unlock` and `tryLock` happens at the same time when there is an existing lock
        //
        // Steps:
        // 1. `unlock` removes the lock in the database, but there is a temporary connection failure
        // 2. `lock` finds that there is no lock, so creates a new lock
        // 3. `unlock` retries the lock removal and removes the new lock
        //

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Expected during cancellation — confirm the shutdown was intentional
  2. If unexpected, trace the interrupt source (Flink cancel, executor shutdownNow) and fix lifecycle handling
  3. Speed up the database (indexes on lock table keys) so isHeld completes quickly
  4. Respect the restored interrupt flag; do not retry in a loop while interrupted
Defensive patterns

Strategy: try-catch

Try / catch

try {
  lock.isHeld();
} catch (UncheckedInterruptedException e) {
  Thread.currentThread().interrupt();
  // treat as unknown lock state; abort current maintenance cycle
}

Prevention

When it happens

Trigger: isHeld's SELECT against the lock table is interrupted — typically Flink task cancellation or executor shutdown while isHeld runs inside the tryLock recovery path.

Common situations: Job cancel/failover while the lock state check runs; slow database making the check window long enough to catch an interrupt; shutdown of the maintenance scheduler thread pool.

Related errors


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