{"record":{"id":"c99f5e505c4cd0ec","repo":"apache/iceberg","slug":"could-not-find-lock-with-hmsclient","errorCode":null,"errorMessage":"Could not find lock with HMSClient {}","messagePattern":"Could not find lock with HMSClient (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java","lineNumber":401,"sourceCode":"    return null;\n  }\n\n  private void unlock(Optional<Long> lockId) {\n    Long id = null;\n    try {\n      if (!lockId.isPresent()) {\n        // Try to find the lock based on agentInfo. Only works with Hive 2 or later.\n        if (HiveVersion.min(HiveVersion.HIVE_2)) {\n          LockInfo lockInfo = findLock();\n          if (lockInfo == null) {\n            // No lock found\n            LOG.info(\"No lock found with {} agentInfo\", agentInfo);\n            return;\n          }\n\n          id = lockInfo.lockId;\n        } else {\n          LOG.warn(\"Could not find lock with HMSClient {}\", HiveVersion.current());\n          return;\n        }\n      } else {\n        id = lockId.get();\n      }\n\n      doUnlock(id);\n    } catch (InterruptedException ie) {\n      if (id != null) {\n        // Interrupted unlock. We try to unlock one more time if we have a lockId\n        try {\n          Thread.interrupted(); // Clear the interrupt status flag for now, so we can retry unlock\n          LOG.warn(\"Interrupted unlock we try one more time {}.{}\", databaseName, tableName, ie);\n          doUnlock(id);\n        } catch (Exception e) {\n          LOG.warn(\"Failed to unlock even on 2nd attempt {}.{}\", databaseName, tableName, e);\n        } finally {\n          Thread.currentThread().interrupt(); // Set back the interrupt status","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java#L383-L419","documentation":"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.","triggerScenarios":"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.","commonSituations":"Interrupted commits leaving stale state; HMS purging abandoned locks; calling unlock from a different process than the one that acquired the lock.","solutions":["Treat as benign — log-only; the lock no longer exists in HMS so no cleanup is needed","Check HMS SHOW LOCKS to confirm no leaked locks remain for the table","If locks leak regularly, inspect whether commits are crashing before unlock and add retry/finalization","Ensure the same process/session that acquired the lock performs the unlock"],"exampleFix":"// before\nlock.unlock(); // warns: could not find lock\n// after\ntry (MetastoreLock lock = ...acquireLock()) {\n  // commit work\n} // unlock called exactly once on close","handlingStrategy":"try-catch","validationCode":"// confirm lock state before unlock\nList<ShowLocksResponseElement> locks = client.showLocks(new ShowLocksRequest(db, table)).getLocks();","typeGuard":null,"tryCatchPattern":"try { lock.close(); } catch (Exception e) { LOG.warn(\"lock already gone or unlock failed\", e); } // absence is benign","preventionTips":["Always use try-with-resources so unlock runs exactly once","Never unlock from a different process/session than acquired","Audit SHOW LOCKS periodically for leaked locks"],"tags":["hive","lock","metastore","unlock"],"backgroundTag":"entity-not-found","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"}