apache/iceberg · error · LockException

Lock is not active

Error message

Lock is not active

What it means

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.

Source

Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/MetastoreLock.java:156

  @Override
  public void lock() throws LockException {
    // getting a process-level lock per table to avoid concurrent commit attempts to the same table
    // from the same JVM process, which would result in unnecessary HMS lock acquisition requests
    acquireJvmLock();

    // Getting HMS lock
    hmsLockId = Optional.of(acquireLock());

    // Starting heartbeat for the HMS lock
    heartbeat = new Heartbeat(metaClients, hmsLockId.get(), lockHeartbeatIntervalTime);
    heartbeat.schedule(exitingScheduledExecutorService);
  }

  @Override
  public void ensureActive() throws LockException {
    if (heartbeat == null) {
      throw new LockException("Lock is not active");
    }

    if (heartbeat.encounteredException != null) {
      throw new LockException(
          heartbeat.encounteredException,
          "Failed to heartbeat for hive lock. %s",
          heartbeat.encounteredException.getMessage());
    }
    if (!heartbeat.active()) {
      throw new LockException("Hive lock heartbeat thread not active");
    }
  }

  @Override
  public void unlock() {
    if (heartbeat != null) {
      heartbeat.cancel();
      exitingScheduledExecutorService.shutdown();

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure lock() successfully acquired the lock and started the heartbeat before any commit is attempted.
  2. Do not reuse a MetastoreLock instance after unlock()/close(); acquire a fresh lock per commit.
  3. Check acquisition logs for earlier failures that left the lock in an uninitialized state.

Example fix

// before
MetastoreLock lock = ...;
lock.unlock();
lock.ensureActive(); // fails: Lock is not active

// after
lock.ensureActive(); // validate while held
... doCommit ...
lock.unlock(); // only when done
Defensive patterns

Strategy: type-guard

Type guard

boolean lockActive(MetastoreLock lock) {
  return lock != null && lockHeartbeatStarted(lock); // heartbeat != null and running
}

Try / catch

try {
  lock.ensureActive();
  commit();
} catch (LockException e) {
  // re-acquire lock and retry commit
}

Prevention

When it happens

Trigger: Calling lock()/doCommit path when MetastoreLock's heartbeat was never initialized — e.g. lock acquisition path skipped heartbeat start, or ensureActive invoked after unlock.

Common situations: Programming errors in custom subclasses of the lock; using a lock instance after close/unlock; failed lock acquisition leaving heartbeat null.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/023bb57db87cdb4f. Report an issue: GitHub.