apache/iceberg · error · RuntimeException

Failed to check Zookeeper lock status

Error message

Failed to check Zookeeper lock status

What it means

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.

Source

Thrown at flink/v2.1/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 the wrapped KeeperException (ConnectionLoss vs SessionExpired)
  2. Rely on Curator's retry policy — increase retries/timeout in createRetryPolicy configuration
  3. Reacquire the lock: after SessionExpired, recreate the lock factory/connection
  4. Stabilize the network between Flink TaskManagers and the Zookeeper quorum
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: verify session is live before lock operations
if (!curator.getZookeeperClient().isConnected()) { reconnect(); }

Try / catch

try {
  boolean held = lock.isHeld();
} catch (RuntimeException e) {
  if (e.getMessage().contains("Failed to check Zookeeper lock status")) {
    // treat as unknown ownership: reacquire the lock after reconnect
  } else { throw e; }
}

Prevention

When it happens

Trigger: tryLock or isHeld invoked while the Zookeeper session is expired or the connection is down; versionedValue.getValue() throws on corrupt/unreadable counter data.

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

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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