apache/iceberg · warning · UncheckedInterruptedException
Interrupted during isHeld
Error message
Interrupted during isHeld
What it means
JdbcLock.isHeld runs a SELECT through the connection pool to check the lock row's instance ID. If the thread is interrupted during that query, the interrupt flag is restored and UncheckedInterruptedException('Interrupted during isHeld') is thrown; SQLException instead becomes 'Failed to check the state of the lock'.
Source
Thrown at flink/v1.20/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
- If part of intentional cancellation, ignore and shut down cleanly.
- If unexpected, find the interrupting component (cancel command, watchdog) and align shutdown ordering.
- Reduce lock-table query latency (indexes, DB load) so isHeld completes fast.
- Restart the trigger job to re-attempt lock acquisition.
Example fix
// no code fix; operational: ensure graceful shutdown stops the trigger loop before cancelling tasks
Defensive patterns
Strategy: try-catch
Validate before calling
// avoid calling isHeld on an interrupted thread
if (Thread.currentThread().isInterrupted()) {
throw new IllegalStateException("Thread already interrupted");
} Try / catch
try {
held = lock.isHeld();
} catch (UncheckedInterruptedException e) {
Thread.currentThread().interrupt();
throw e; // propagate as cancellation
} Prevention
- Stop the trigger loop gracefully before cancelling tasks
- Keep lock-table queries fast (proper indexes, low DB load)
- Avoid long blocking operations sharing the trigger thread
- Always restore the interrupt flag when catching InterruptedException
When it happens
Trigger: isHeld (invoked during tryLock's failure-recovery path or by the trigger loop) interrupted mid-SELECT — job cancel/failover while querying the lock table.
Common situations: Cancellation during lock-state verification; slow SELECTs on a contended DB widening the interruption window.
Related errors
- Interrupted during tryLock
- Interrupted in call to initialize
- Interrupted during isHeld
- Interrupted during unlock
- Failed to create %s lock
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/d9ef433f373cff6b.
Report an issue: GitHub.