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 statusView on GitHub (pinned to 86d9c8fc54)
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
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
- 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
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
- Failed to unlock {}.{}
- Failed to create lock {}
- Failed to release lock
- Interrupted during unlock
- Failed to remove lock %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/c99f5e505c4cd0ec.
Report an issue: GitHub.