{"record":{"id":"9c8b80b93c1a63c7","repo":"apache/iceberg","slug":"could-not-acquire-the-lock-on-s-s-lock-request","errorCode":null,"errorMessage":"Could not acquire the lock on %s.%s, lock request ended in state %s","messagePattern":"Could not acquire the lock on (.+?)\\.(.+?), lock request ended in state (.+?)","errorType":"exception","errorClass":"LockException","httpStatus":null,"severity":"error","filePath":"hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java","lineNumber":254,"sourceCode":"    } finally {\n      if (!lockInfo.lockState.equals(LockState.ACQUIRED)) {\n        unlock(Optional.of(lockInfo.lockId));\n      }\n    }\n\n    if (!lockInfo.lockState.equals(LockState.ACQUIRED)) {\n      if (timeout) {\n        throw new LockException(\n            \"Timed out after %s ms waiting for lock on %s.%s\", duration, databaseName, tableName);\n      }\n\n      if (thriftError != null) {\n        throw new LockException(\n            thriftError, \"Metastore operation failed for %s.%s\", databaseName, tableName);\n      }\n\n      // Just for safety. We should not get here.\n      throw new LockException(\n          \"Could not acquire the lock on %s.%s, lock request ended in state %s\",\n          databaseName, tableName, lockInfo.lockState);\n    } else {\n      return lockInfo.lockId;\n    }\n  }\n\n  /**\n   * Creates a lock, retrying if possible on failure.\n   *\n   * @return The {@link LockInfo} object for the successfully created lock\n   * @throws LockException When we are not able to fill the hostname for lock creation, or there is\n   *     an error during lock creation\n   */\n  @SuppressWarnings(\"ReverseDnsLookup\")\n  private LockInfo createLock() throws LockException {\n    LockInfo lockInfo = new LockInfo();\n","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java#L236-L272","documentation":"MetastoreLock acquires an exclusive Hive metastore lock for a table commit. After issuing the lock request, the code polls until the lock is acquired; if the loop exits without an acquired lock and without a recorded thrift error, this safety-net LockException is thrown reporting the final lock state. It indicates the lock request ended in an unexpected state (e.g. WAITING/ABORT) rather than ACQUIRED.","triggerScenarios":"Calling commit on a Hive-catalog table when the metastore lock request terminates in a non-ACQUIRED state: the lock is aborted by another holder, the wait loop exhausts, or Hive returns a state the polling loop does not handle.","commonSituations":"Concurrent writers contending for the same table until one lock is aborted; Hive metastore under heavy load returning slow lock acquisition; long-running commits exceeding Hive's lock timeout (hive.txn.timeout) so the lock is reaped while waiting.","solutions":["Check for concurrent writers/engines holding locks on the table and reduce contention (SHOW LOCKS on the table in Hive).","Increase the lock acquisition retry/wait budget and Hive lock timeout so transient WAITING states resolve to ACQUIRED.","Inspect lockInfo.lockState in the message: if ABORTED, the request was rejected — re-run the commit; if still WAITING, tune metastore lock checker intervals.","Verify Hive metastore connectivity and health; persistent failures usually surface as thriftError instead, but flaky RPCs can leave odd states."],"exampleFix":"// before\nTable table = HiveCatalog.loadTable(identifier);\ntable.refresh(); // retry commit manually after lock failure\n// after\nTasks.foreach(table).retry(3).exponentialBackoff(1000, 15000)\n    .throwFailureWhenFinished();\nRefreshOperation... table.refresh(); table.commit(); // re-attempt under lock","handlingStrategy":"retry","validationCode":"// check for competing locks before committing\n// in Hive: SHOW LOCKS <db>.<table>;  or via IMetaStoreClient showLocks()\n// proceed only if no EXCLUSIVE/WAITING locks exist","typeGuard":null,"tryCatchPattern":"try {\n  table.refresh();\n  table.commit(apply);\n} catch (LockException | CommitFailedException e) {\n  // inspect lockState in message; backoff and retry\n  backoffRetry(() -> { table.refresh(); table.commit(apply); });\n}","preventionTips":["Minimize concurrent writers to the same Hive-catalog table","Keep commits short-lived; avoid slow scan planning inside the lock window","Tune hive.txn.timeout and lock retry budgets above worst-case commit duration","Monitor SHOW LOCKS output for stuck WAITING/ABORT states"],"tags":["hive","locking","concurrency","metastore"],"backgroundTag":"lock-acquisition-failed","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"}