{"record":{"id":"4846f8b1c36e8e34","repo":"apache/iceberg","slug":"interrupted-during-unlock-4846f8","errorCode":null,"errorMessage":"Interrupted during unlock","messagePattern":"Interrupted during unlock","errorType":"exception","errorClass":"UncheckedInterruptedException","httpStatus":null,"severity":"info","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java","lineNumber":270,"sourceCode":"              conn -> {\n                try (PreparedStatement sql = conn.prepareStatement(DELETE_LOCK_SQL)) {\n                  sql.setString(1, type.key);\n                  sql.setString(2, lockId);\n                  sql.setString(3, instanceId);\n                  long count = sql.executeUpdate();\n                  LOG.info(\n                      \"Deleted {} lock with instanceId {} with row count {}\",\n                      this,\n                      instanceId,\n                      count);\n                }\n\n                return null;\n              });\n        }\n      } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n        throw new UncheckedInterruptedException(e, \"Interrupted during unlock\");\n      } catch (SQLException e) {\n        // SQL exception happened when getting/updating lock information\n        throw new UncheckedSQLException(e, \"Failed to remove lock %s\", this);\n      }\n    }\n\n    @Override\n    public String toString() {\n      return MoreObjects.toStringHelper(this).add(\"type\", type).add(\"lockId\", lockId).toString();\n    }\n\n    @SuppressWarnings(\"checkstyle:NestedTryDepth\")\n    private String instanceId() {\n      try {\n        return pool.run(\n            conn -> {\n              try (PreparedStatement sql = conn.prepareStatement(GET_LOCK_SQL)) {\n                sql.setString(1, type.key);","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/JdbcLockFactory.java#L252-L288","documentation":"Thrown by JdbcLock.unlock when the thread is interrupted while the DELETE (or lock-info read/update) that releases the maintenance lock is running. The interrupt flag is restored and the InterruptedException is wrapped in UncheckedInterruptedException. The lock release may not have completed — check the lock table state.","triggerScenarios":"unlock is called (normally when the maintenance task closes) and the thread is interrupted mid SQL execution — task cancellation or Flink failover during close().","commonSituations":"Flink cancels the job while close() releases the lock; shutdownNow on the executor during unlock; failover racing with lock release.","solutions":["Expected during cancellation, but verify afterwards that the lock row was deleted to avoid a stale lock","If a stale lock remains, delete it manually from the lock table before the next maintenance run","If unexpected, find the interrupt source and adjust task lifecycle/shutdown ordering","Respect the restored interrupt flag in surrounding code"],"exampleFix":"// after catching during shutdown, clean up any stale lock\ntry {\n  lock.unlock();\n} catch (UncheckedInterruptedException e) {\n  Thread.currentThread().interrupt();\n  jdbcCleanup.deleteStaleLockRow(lockId); // avoid orphaned lock\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  lock.unlock();\n} catch (UncheckedInterruptedException e) {\n  Thread.currentThread().interrupt();\n  // schedule a stale-lock sweep; release may not have completed\n}","preventionTips":["After any interrupted unlock, sweep the lock table for rows owned by the dead instance","Order shutdown so unlock completes before aggressive cancellation","Use lock rows with timestamps so stale locks are easy to identify and purge"],"tags":["interrupted","locking","jdbc","unlock","flink"],"backgroundTag":"operation-interrupted","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}