{"record":{"id":"023bb57db87cdb4f","repo":"apache/iceberg","slug":"lock-is-not-active","errorCode":null,"errorMessage":"Lock is not active","messagePattern":"Lock is not active","errorType":"exception","errorClass":"LockException","httpStatus":null,"severity":"error","filePath":"hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java","lineNumber":156,"sourceCode":"\n  @Override\n  public void lock() throws LockException {\n    // getting a process-level lock per table to avoid concurrent commit attempts to the same table\n    // from the same JVM process, which would result in unnecessary HMS lock acquisition requests\n    acquireJvmLock();\n\n    // Getting HMS lock\n    hmsLockId = Optional.of(acquireLock());\n\n    // Starting heartbeat for the HMS lock\n    heartbeat = new Heartbeat(metaClients, hmsLockId.get(), lockHeartbeatIntervalTime);\n    heartbeat.schedule(exitingScheduledExecutorService);\n  }\n\n  @Override\n  public void ensureActive() throws LockException {\n    if (heartbeat == null) {\n      throw new LockException(\"Lock is not active\");\n    }\n\n    if (heartbeat.encounteredException != null) {\n      throw new LockException(\n          heartbeat.encounteredException,\n          \"Failed to heartbeat for hive lock. %s\",\n          heartbeat.encounteredException.getMessage());\n    }\n    if (!heartbeat.active()) {\n      throw new LockException(\"Hive lock heartbeat thread not active\");\n    }\n  }\n\n  @Override\n  public void unlock() {\n    if (heartbeat != null) {\n      heartbeat.cancel();\n      exitingScheduledExecutorService.shutdown();","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java#L138-L174","documentation":"MetastoreLock.ensureActive was called before the heartbeat thread was started, so there is no live lock to validate. The LockException signals the caller (usually doCommit during the final check) that the lock is not in an active state.","triggerScenarios":"Calling lock()/doCommit path when MetastoreLock's heartbeat was never initialized — e.g. lock acquisition path skipped heartbeat start, or ensureActive invoked after unlock.","commonSituations":"Programming errors in custom subclasses of the lock; using a lock instance after close/unlock; failed lock acquisition leaving heartbeat null.","solutions":["Ensure lock() successfully acquired the lock and started the heartbeat before any commit is attempted.","Do not reuse a MetastoreLock instance after unlock()/close(); acquire a fresh lock per commit.","Check acquisition logs for earlier failures that left the lock in an uninitialized state."],"exampleFix":"// before\nMetastoreLock lock = ...;\nlock.unlock();\nlock.ensureActive(); // fails: Lock is not active\n\n// after\nlock.ensureActive(); // validate while held\n... doCommit ...\nlock.unlock(); // only when done","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean lockActive(MetastoreLock lock) {\n  return lock != null && lockHeartbeatStarted(lock); // heartbeat != null and running\n}","tryCatchPattern":"try {\n  lock.ensureActive();\n  commit();\n} catch (LockException e) {\n  // re-acquire lock and retry commit\n}","preventionTips":["Acquire a fresh lock per commit; never reuse after unlock/close.","Check that lock() succeeded (non-null lockId) before committing."],"tags":["hive","locking","lifecycle","state"],"backgroundTag":"invalid-state-transition","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"}