{"record":{"id":"2e3011946a22eaf0","repo":"apache/iceberg","slug":"failed-to-check-zookeeper-lock-status-2e3011","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.2/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.2/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/ZkLockFactory.java#L214-L250","documentation":"ZkLockFactory's lock compares a versioned SharedCount value against LOCKED to decide whether the lock is held. If reading the value from ZooKeeper throws any Exception (connection loss, session expired, node missing), it is wrapped in RuntimeException(\"Failed to check Zookeeper lock status\"). This prevents treating an unreadable lock state as \"unlocked\".","triggerScenarios":"tryLock or isHeld reads the SharedCount's VersionedValue and the underlying ZK get fails: connection loss, session expiry, the counter znode has not been created/started, or the znode was deleted externally.","commonSituations":"ZooKeeper session expired after a GC pause or network partition; someone/something deleted the trigger's znode path; open() was never called so the SharedCounts are not running; flaky network between Flink and the ensemble.","solutions":["Check the wrapped cause for KeeperException types (CONNECTIONLOSS, SESSIONEXPIRED, NONODE) and address that specific problem.","Ensure open() (or factory.create()) was invoked before tryLock; isHeld on an unstarted SharedCount fails.","Verify the znode path for the lockId still exists; recreate it by re-opening the factory if it was deleted.","Stabilize the ZK session (tune session timeout, avoid long GC pauses) and retry the operation with backoff.","Run only one instance per lockId to avoid external interference with the counter znode."],"exampleFix":"// before\nLock lock = factory.createLock(); // open() never called\nboolean locked = lock.tryLock(); // -> Failed to check Zookeeper lock status\n// after\nLockFactory lf = factory.create(); // opens client + SharedCounts\nLock lock = lf.createLock();\nboolean locked = lock.tryLock();","handlingStrategy":"retry","validationCode":"if (!lockFactory.isInitialized() /* ensure open() ran */) throw new IllegalStateException(\"Call create()/open() before tryLock\");","typeGuard":null,"tryCatchPattern":"try { boolean locked = lock.tryLock(); } catch (RuntimeException e) { if (\"Failed to check Zookeeper lock status\".equals(e.getMessage())) { /* check ZK session, retry with backoff */ } else throw e; }","preventionTips":["Always initialize via factory create()/open() before any lock operations.","Tune ZK session timeout and avoid long GC pauses that expire sessions.","Monitor KeeperException causes: CONNECTIONLOSS vs SESSIONEXPIRED vs NONODE need different fixes.","Protect trigger znodes from external deletion and run a single instance per lockId."],"tags":["zookeeper","curator","lock","flink","session-expired"],"backgroundTag":"zookeeper-session-expired","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"}