apache/iceberg · critical · CommitStateUnknownException

Failed to heartbeat for hive lock while committing changes…

Error message

Failed to heartbeat for hive lock while committing changes. This can lead to a concurrent commit attempt be able to overwrite this commit. Please check the commit history. If you are running into this issue, try reducing iceberg.hive.lock-heartbeat-interval-ms.

What it means

After persisting the view, doCommit calls lock.ensureActive() to verify the Hive lock heartbeat is still alive. If the heartbeat failed (LockException), the commit's outcome is uncertain — another commit may overwrite it — so it throws CommitStateUnknownException with commitStatus UNKNOWN. Callers must check history rather than assume success or failure.

Solutions

  1. Inspect the view's commit history/metadata location to determine whether the commit landed before retrying — do NOT blindly re-commit.
  2. Lower iceberg.hive.lock-heartbeat-interval-ms so heartbeats survive slow commits.
  3. Check HMS connectivity and lock table state; re-run after the metastore is healthy.
  4. Treat CommitStateUnknownException as non-retryable-automatically; reconcile state first (Iceberg will resolve to the last successful commit).

Example fix

// before
try { view.replaceView(...).commit(); } catch (CommitStateUnknownException e) { retry(); }
// after
catch (CommitStateUnknownException e) {
  View current = views.loadView(identifier); // check which commit actually won
  // reconcile with current state before any retry
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Keep heartbeat interval safely below expected commit duration
String interval = conf.get("iceberg.hive.lock-heartbeat-interval-ms");
// e.g., ensure interval < (expected commit time / 3)

Try / catch

try {
  view.replaceView(...).commit();
} catch (CommitStateUnknownException e) {
  // DO NOT auto-retry; inspect current metadata/history to learn if commit landed
  View current = views.loadView(identifier);
  // reconcile against current state
}

Prevention

When it happens

Trigger: Committing a Hive view while holding a Hive lock whose heartbeat fails — e.g., HMS unreachable during heartbeat, lock expired due to long commit, or heartbeat interval too large (iceberg.hive.lock-heartbeat-interval-ms too high).

Common situations: Long garbage-collection pauses or network interruptions during commit; HMS restarts mid-commit; lock expiry under slow metastore operations; misconfigured heartbeat interval.

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/a4a5782495446ae5. Report an issue: GitHub.

Appendix: source

Thrown at hive-metastore/src/main/java/org/apache/iceberg/hive/HiveViewOperations.java:196

      }
      HMSTablePropertyHelper.updateHmsTableForIcebergView(
          newMetadataLocation,
          tbl,
          metadata,
          removedProps,
          maxHiveTablePropertySize,
          currentMetadataLocation(),
          sqlFor(metadata));
      lock.ensureActive();

      try {
        persistTable(tbl, updateHiveView, hiveLockEnabled(conf) ? null : baseMetadataLocation);
        lock.ensureActive();

        commitStatus = CommitStatus.SUCCESS;
      } catch (LockException le) {
        commitStatus = CommitStatus.UNKNOWN;
        throw new CommitStateUnknownException(
            "Failed to heartbeat for hive lock while "
                + "committing changes. This can lead to a concurrent commit attempt be able to overwrite this commit. "
                + "Please check the commit history. If you are running into this issue, try reducing "
                + "iceberg.hive.lock-heartbeat-interval-ms.",
            le);
      } catch (org.apache.hadoop.hive.metastore.api.AlreadyExistsException e) {
        throw new AlreadyExistsException(e, "View already exists: %s.%s", database, viewName);

      } catch (InvalidObjectException e) {
        throw new ValidationException(e, "Invalid Hive object for %s.%s", database, viewName);

      } catch (CommitFailedException | CommitStateUnknownException e) {
        throw e;

      } catch (Throwable e) {
        if (e.getMessage() != null
            && e.getMessage()
                .contains(

View on GitHub (pinned to 86d9c8fc54)