apache/iceberg · error · RuntimeException

Failed to check Zookeeper lock status

Error message

Failed to check Zookeeper lock status

What it means

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.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/ZkLockFactory.java:232

        }

        return acquired;
      } catch (Exception e) {
        LOG.warn("Failed to acquire Zookeeper lock", e);
        return false;
      }
    }

    @Override
    public boolean isHeld() {
      return isHeld(sharedCount.getVersionedValue());
    }

    private static boolean isHeld(VersionedValue<Integer> versionedValue) {
      try {
        return versionedValue.getValue() == LOCKED;
      } catch (Exception e) {
        throw new RuntimeException("Failed to check Zookeeper lock status", e);
      }
    }

    @Override
    public void unlock() {
      try {
        sharedCount.setCount(UNLOCKED);
        LOG.debug("Released lock for path: {}", lockPath);
      } catch (Exception e) {
        LOG.warn("Failed to release lock for path: {}", lockPath, e);
        throw new RuntimeException("Failed to release lock", e);
      }
    }
  }

  @VisibleForTesting
  RetryPolicy createRetryPolicy() {
    ZKRetryPolicies effectivePolicy =

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check getCause() for KeeperException.ConnectionLoss vs NoNode vs deserialization errors.
  2. Restore ZooKeeper connectivity/quorum; the Curator retryPolicy should absorb brief outages.
  3. Recreate the lock znode if it was deleted externally (start the counter again at 0/UNLOCKED).
  4. Ensure all writers use the same Iceberg/Curator versions to avoid incompatible counter serialization.
  5. Increase session timeout and tune the Curator retry policy for unstable networks.
Defensive patterns

Strategy: retry

Validate before calling

// preflight read
zkCli.sh -server zk:2181 get /iceberg/lock/<lockId>/task

Try / catch

try {
  boolean held = lock.tryLock(/*waitTime*/);
} catch (RuntimeException e) {
  LOG.warn("ZK lock status check failed, retrying", e.getCause());
  // retry with backoff; treat repeated failure as 'not held'
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/67e775b996556297. Report an issue: GitHub.