{"record":{"id":"3496b24d733bdfe5","repo":"apache/iceberg","slug":"failed-to-release-lock","errorCode":null,"errorMessage":"Failed to release lock","messagePattern":"Failed to release lock","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":243,"sourceCode":"      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 =\n        (retryPolicy == null) ? ZKRetryPolicies.EXPONENTIAL_BACKOFF : retryPolicy;\n\n    switch (effectivePolicy) {\n      case ONE_TIME:\n        return new RetryOneTime(baseSleepTimeMs);\n\n      case N_TIME:\n        return new RetryNTimes(maxRetries, baseSleepTimeMs);\n\n      case BOUNDED_EXPONENTIAL_BACKOFF:\n        return new BoundedExponentialBackoffRetry(baseSleepTimeMs, maxSleepTimeMs, maxRetries);","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/api/ZkLockFactory.java#L225-L261","documentation":"ZkLock.unlock() failed to set the shared counter back to UNLOCKED; after logging a warning it throws RuntimeException('Failed to release lock', e). The lock may remain held in ZooKeeper and block future maintenance triggers.","triggerScenarios":"sharedCount.setCount(UNLOCKED) throws: session expired (ConnectionLoss), NoAuth on the znode, the versioned set fails because the node changed concurrently, or the znode was deleted externally before the write.","commonSituations":"ZooKeeper maintenance/failover during unlock; ACLs changed so the client can no longer write; two instances racing on the same lockId causing a BadVersion error; manual znode deletion by an operator.","solutions":["Inspect getCause(); if ConnectionLoss/BadVersion, retry unlock() once the session re-establishes.","Manually reset the counter znode (or delete it) to clear a stuck lock, then let the factory reinitialize it.","Fix ACLs so the client principal has write access to the lock path.","Avoid sharing the same lockId across concurrent triggers; give each trigger a unique lockId.","Use unique lockIds and short session timeouts so expired locks self-release on session close."],"exampleFix":"// before\nZkLockFactory.builder().setLockId(\"maintenance\")  // shared by two jobs -> version conflicts\n// after\nZkLockFactory.builder().setLockId(\"maintenance-daily-aggregate\") // unique per trigger","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  lock.unlock();\n} catch (RuntimeException e) {\n  LOG.error(\"Release failed; lock {} may stay held\", lockId, e.getCause());\n  // retry unlock with backoff, else manually reset the counter znode\n}","preventionTips":["Assign a unique lockId per trigger to avoid version conflicts","Keep ACL write permissions stable for the client principal","Retry unlock on transient ConnectionLoss before manual cleanup","Monitor session expiry and reconnect before unlocking"],"tags":["flink","zookeeper","lock","unlock"],"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"}