{"record":{"id":"3be343c01fe90bdc","repo":"apache/iceberg","slug":"failed-to-check-zookeeper-lock-status-3be343","errorCode":null,"errorMessage":"Failed to check Zookeeper lock status","messagePattern":"Failed to check Zookeeper lock status","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/ZkLockFactory.java","lineNumber":232,"sourceCode":"        }\n\n        return acquired;\n      } catch (Exception e) {\n        LOG.warn(\"Failed to acquire Zookeeper lock\", e);\n        return false;\n      }\n    }\n\n    @Override\n    public boolean isHeld() {\n      return isHeld(sharedCount.getVersionedValue());\n    }\n\n    private static boolean isHeld(VersionedValue<Integer> versionedValue) {\n      try {\n        return versionedValue.getValue() == LOCKED;\n      } catch (Exception e) {\n        throw new RuntimeException(\"Failed to check Zookeeper lock status\", e);\n      }\n    }\n\n    @Override\n    public void unlock() {\n      try {\n        sharedCount.setCount(UNLOCKED);\n        LOG.debug(\"Released lock for path: {}\", lockPath);\n      } catch (Exception e) {\n        LOG.warn(\"Failed to release lock for path: {}\", lockPath, e);\n        throw new RuntimeException(\"Failed to release lock\", e);\n      }\n    }\n  }\n\n  @VisibleForTesting\n  RetryPolicy createRetryPolicy() {\n    ZKRetryPolicies effectivePolicy =","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/ZkLockFactory.java#L214-L250","documentation":"The lock's isHeld(VersionedValue) reads the current counter value from Zookeeper to compare against LOCKED; any exception doing so (session expired, connection loss, deserialization) is wrapped in this RuntimeException. Callers cannot determine lock ownership, so the failure is propagated rather than assumed.","triggerScenarios":"tryLock or isHeld invoked while the Zookeeper session is expired or the connection is down; versionedValue.getValue() throws on corrupt/unreadable counter data.","commonSituations":"Long GC pauses or network partitions expiring the Zookeeper session; Zookeeper ensemble restart while a maintenance task holds/queries the lock; reconnect window during a SharedCount read.","solutions":["Check the wrapped KeeperException (ConnectionLoss vs SessionExpired)","Rely on Curator's retry policy — increase retries/timeout in createRetryPolicy configuration","Reacquire the lock: after SessionExpired, recreate the lock factory/connection","Stabilize the network between Flink TaskManagers and the Zookeeper quorum"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: verify session is live before lock operations\nif (!curator.getZookeeperClient().isConnected()) { reconnect(); }","typeGuard":null,"tryCatchPattern":"try {\n  boolean held = lock.isHeld();\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"Failed to check Zookeeper lock status\")) {\n    // treat as unknown ownership: reacquire the lock after reconnect\n  } else { throw e; }\n}","preventionTips":["Keep GC pauses and network partitions below Zookeeper session timeout","Configure Curator retry policy with sufficient retries","Monitor session-expiration events and rebuild the lock factory on them"],"tags":["zookeeper","lock","session-expired","flink"],"backgroundTag":"connection-refused","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"}