{"record":{"id":"25e4f6353a24f8f4","repo":"apache/iceberg","slug":"timed-out-after-s-ms-waiting-for-lock-on-s-s","errorCode":null,"errorMessage":"Timed out after %s ms waiting for lock on %s.%s","messagePattern":"Timed out after (.+?) ms waiting for lock on (.+?)\\.(.+?)","errorType":"exception","errorClass":"LockException","httpStatus":null,"severity":"error","filePath":"hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java","lineNumber":244,"sourceCode":"                        e);\n                  }\n                },\n                TException.class);\n      }\n    } catch (WaitingForLockException e) {\n      timeout = true;\n      duration = System.currentTimeMillis() - start;\n    } catch (TException e) {\n      thriftError = e;\n    } 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  /**","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java#L226-L262","documentation":"The lock acquisition loop gave up after the configured timeout without reaching ACQUIRED state. Iceberg throws LockException with the waited duration and table coordinates, and the commit is abandoned (it will surface as a CommitFailedException upstream).","triggerScenarios":"acquireLock ran its full retry window with checkLock repeatedly returning WAITING (or not ACQUIRED) and timeout=true; called from lock() during doCommit under heavy contention or a stuck competing transaction.","commonSituations":"Long-running or hung Hive transaction blocking the table; many concurrent writers; lock timeout configured too low for legitimate contention.","solutions":["Increase the lock acquisition timeout in the Hive catalog/lock configuration.","Identify and resolve the competing lock holder (SHOW LOCKS, Hive transaction list, kill stale transactions).","Reduce concurrent writers or stagger job schedules to avoid overlap.","Retry the commit once the lock is available."],"exampleFix":"// before\nCatalogUtil lock config: lock acquisition timeout = 1000ms (too low)\n\n// after\nset hive catalog lock acquisition/heartbeat timeouts to allow\nrealistic waits, e.g. several minutes, then retry commit on failure","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  commit();\n} catch (CommitFailedException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Timed out\")) {\n    // verify lock holder gone, then re-acquire and retry with backoff\n  }\n}","preventionTips":["Configure a lock acquisition timeout that reflects realistic contention.","Kill hung Hive transactions instead of letting them block lock waits.","Limit concurrent writers per table."],"tags":["hive","locking","timeout","contention"],"backgroundTag":"request-timeout","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"}