apache/iceberg · info

Could not find lock with HMSClient {}

Error message

Could not find lock with HMSClient {}

What it means

MetastoreLock.unlock needs a lockId to release the lock. When no lockId is known, it looks the lock up via HMSClient (showLocks/agentInfo); if that lookup cannot find the lock, it logs this warning and returns without unlocking. It usually means the lock was already released or never created.

Source

Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java:401

    return null;
  }

  private void unlock(Optional<Long> lockId) {
    Long id = null;
    try {
      if (!lockId.isPresent()) {
        // Try to find the lock based on agentInfo. Only works with Hive 2 or later.
        if (HiveVersion.min(HiveVersion.HIVE_2)) {
          LockInfo lockInfo = findLock();
          if (lockInfo == null) {
            // No lock found
            LOG.info("No lock found with {} agentInfo", agentInfo);
            return;
          }

          id = lockInfo.lockId;
        } else {
          LOG.warn("Could not find lock with HMSClient {}", HiveVersion.current());
          return;
        }
      } else {
        id = lockId.get();
      }

      doUnlock(id);
    } catch (InterruptedException ie) {
      if (id != null) {
        // Interrupted unlock. We try to unlock one more time if we have a lockId
        try {
          Thread.interrupted(); // Clear the interrupt status flag for now, so we can retry unlock
          LOG.warn("Interrupted unlock we try one more time {}.{}", databaseName, tableName, ie);
          doUnlock(id);
        } catch (Exception e) {
          LOG.warn("Failed to unlock even on 2nd attempt {}.{}", databaseName, tableName, e);
        } finally {
          Thread.currentThread().interrupt(); // Set back the interrupt status

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Treat as benign — log-only; the lock no longer exists in HMS so no cleanup is needed
  2. Check HMS SHOW LOCKS to confirm no leaked locks remain for the table
  3. If locks leak regularly, inspect whether commits are crashing before unlock and add retry/finalization
  4. Ensure the same process/session that acquired the lock performs the unlock

Example fix

// before
lock.unlock(); // warns: could not find lock
// after
try (MetastoreLock lock = ...acquireLock()) {
  // commit work
} // unlock called exactly once on close
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm lock state before unlock
List<ShowLocksResponseElement> locks = client.showLocks(new ShowLocksRequest(db, table)).getLocks();

Try / catch

try { lock.close(); } catch (Exception e) { LOG.warn("lock already gone or unlock failed", e); } // absence is benign

Prevention

When it happens

Trigger: unlock() called after the lock was already released (e.g. by a concurrent commit path or HMS timeout), or the HMSClient variant lookup by agentInfo finds no matching lock row.

Common situations: Interrupted commits leaving stale state; HMS purging abandoned locks; calling unlock from a different process than the one that acquired the lock.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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