apache/iceberg · error · UncheckedInterruptedException
Interrupted during unlock
Error message
Interrupted during unlock
What it means
JdbcLock.unlock() removes this trigger's lock row/state from the JDBC lock table. If the thread is interrupted while executing the update/delete SQL, the interrupt flag is restored and an UncheckedInterruptedException is thrown. A stuck unlock can leave the lock held and block subsequent maintenance runs.
Source
Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java:270
conn -> {
try (PreparedStatement sql = conn.prepareStatement(DELETE_LOCK_SQL)) {
sql.setString(1, type.key);
sql.setString(2, lockId);
sql.setString(3, instanceId);
long count = sql.executeUpdate();
LOG.info(
"Deleted {} lock with instanceId {} with row count {}",
this,
instanceId,
count);
}
return null;
});
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new UncheckedInterruptedException(e, "Interrupted during unlock");
} catch (SQLException e) {
// SQL exception happened when getting/updating lock information
throw new UncheckedSQLException(e, "Failed to remove lock %s", this);
}
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).add("type", type).add("lockId", lockId).toString();
}
@SuppressWarnings("checkstyle:NestedTryDepth")
private String instanceId() {
try {
return pool.run(
conn -> {
try (PreparedStatement sql = conn.prepareStatement(GET_LOCK_SQL)) {
sql.setString(1, type.key);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the wrapped cause and job logs to find who interrupted the thread; avoid cancelling during maintenance commits.
- Verify the database is responsive so unlock SQL completes quickly instead of blocking until interrupted.
- After restart, confirm the lock was actually released; clear stale lock rows in the lock table if orphaned.
- Run unlock in shutdown paths that are not interrupted (or tolerate interruption and re-check lock state afterwards).
Example fix
// before
executor.shutdownNow(); // interrupts thread holding the lock mid-unlock
// after
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow(); // interrupt only after unlock had a chance to finish
} Defensive patterns
Strategy: try-catch
Validate before calling
if (Thread.currentThread().isInterrupted()) { /* do not start unlock */ } Try / catch
try { lock.unlock(); } catch (UncheckedInterruptedException e) { Thread.currentThread().interrupt(); /* schedule lock-state re-check */ } Prevention
- Use graceful executor shutdown (shutdown + awaitTermination) instead of shutdownNow during maintenance.
- Keep unlock SQL short; ensure the DB is healthy before committing maintenance.
- After any interruption, re-check and clean stale lock rows.
- Run a single instance per lockId to avoid contention.
When it happens
Trigger: Calling unlock() on a JdbcLock while the thread executing the get/update lock SQL is interrupted (job cancellation, shutdown hook, interrupt from a scheduler).
Common situations: Flink job restart or cancellation during maintenance commit; database hang causing the unlock SQL to block until an external interrupt; thread pool shutdown while maintenance is still finalizing.
Related errors
- Interrupted during tryLock
- Interrupted during isHeld
- Interrupted during unlock
- Interrupted during isHeld
- Failed to remove lock %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/50e59d63e2736d19.
Report an issue: GitHub.