{"record":{"id":"67e775b996556297","repo":"apache/iceberg","slug":"failed-to-check-zookeeper-lock-status","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/v1.20/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/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/ZkLockFactory.java#L214-L250","documentation":"ZkLock.isHeld(VersionedValue<Integer>) calls versionedValue.getValue() on the SharedCount data; any exception (e.g. ConnectionLoss, NoNode, deserialization failure) is wrapped in RuntimeException('Failed to check Zookeeper lock status'). The lock state could not be read from the stored counter.","triggerScenarios":"tryLock()/isHeld() reading the shared count znode when the ZooKeeper session is lost, the znode was deleted externally, the stored data cannot be deserialized (corrupted or written by an incompatible version), or the retry policy is exhausted.","commonSituations":"ZooKeeper ensemble failover during isHeld; external cleanup script removed the lock znode; another Iceberg/Flink version wrote counter bytes in a different format; long GC pause causing session expiry mid-read.","solutions":["Check getCause() for KeeperException.ConnectionLoss vs NoNode vs deserialization errors.","Restore ZooKeeper connectivity/quorum; the Curator retryPolicy should absorb brief outages.","Recreate the lock znode if it was deleted externally (start the counter again at 0/UNLOCKED).","Ensure all writers use the same Iceberg/Curator versions to avoid incompatible counter serialization.","Increase session timeout and tune the Curator retry policy for unstable networks."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight read\nzkCli.sh -server zk:2181 get /iceberg/lock/<lockId>/task","typeGuard":null,"tryCatchPattern":"try {\n  boolean held = lock.tryLock(/*waitTime*/);\n} catch (RuntimeException e) {\n  LOG.warn(\"ZK lock status check failed, retrying\", e.getCause());\n  // retry with backoff; treat repeated failure as 'not held'\n}","preventionTips":["Keep session timeouts above max GC pause","Do not delete lock znodes externally while jobs run","Use identical Iceberg/Curator versions across all writers","Tune the Curator retry policy for your network's failure profile"],"tags":["flink","zookeeper","lock","sharedcount"],"backgroundTag":"zookeeper-connection-loss","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"}