apache/iceberg · warning

Commit status check: Commit to {} of {} unknown, new metadat

Error message

Commit status check: Commit to {} of {} unknown, new metadata location is not current or in history

What it means

This is a WARN log, not a thrown exception: after a commit whose outcome is unclear (e.g. an HTTP timeout), Iceberg re-checks the metastore to determine whether the commit actually succeeded. When the new metadata location is neither the table's current location nor in its history, the commit is definitively a failure, but since the original error was ambiguous, the method conservatively returns CommitStatus.UNKNOWN instead of FAILURE. Callers treat UNKNOWN as unrecoverable and propagate a CommitFailedException-style uncertainty to the user.

Source

Thrown at core/src/main/java/org/apache/iceberg/BaseMetastoreOperations.java:72

   * CommitStatus#UNKNOWN}, because possible pending retries might still commit the change.
   *
   * @param tableOrViewName full name of the Table/View
   * @param newMetadataLocation the path of the new commit file
   * @param properties properties for retry
   * @param commitStatusSupplier check if the latest metadata presents or not using metadata
   *     location for table.
   * @return Commit Status of Success or Unknown
   */
  protected CommitStatus checkCommitStatus(
      String tableOrViewName,
      String newMetadataLocation,
      Map<String, String> properties,
      Supplier<Boolean> commitStatusSupplier) {
    CommitStatus strictStatus =
        checkCommitStatusStrict(
            tableOrViewName, newMetadataLocation, properties, commitStatusSupplier);
    if (strictStatus == CommitStatus.FAILURE) {
      LOG.warn(
          "Commit status check: Commit to {} of {} unknown, new metadata location is not current "
              + "or in history",
          tableOrViewName,
          newMetadataLocation);
      return CommitStatus.UNKNOWN;
    }
    return strictStatus;
  }

  /**
   * Attempt to load the content and see if any current or past metadata location matches the one we
   * were attempting to set. This is used as a last resort when we are dealing with exceptions that
   * may indicate the commit has failed and don't have proof that this is the case, but we can be
   * sure that no retry attempts for the commit will be successful later. Note that all the previous
   * locations must also be searched on the chance that a second committer was able to successfully
   * commit on top of our commit. When the {@code newMetadataLocation} is not in the history the
   * method returns {@link CommitStatus#FAILURE}, when the {@code commitStatusSupplier} fails
   * repeatedly the method returns {@link CommitStatus#UNKNOWN}.

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Re-run the commit operation; UNKNOWN status means the table was not modified by this commit so a fresh commit is safe.
  2. Check the table's current metadata location in the metastore to identify which concurrent writer won.
  3. Reduce commit concurrency or use a catalog with proper atomic commit semantics (e.g. REST catalog with conditional writes) instead of racing clients.
  4. Enable debug logging on the operations class to compare the expected vs actual metadata location.

Example fix

// before: retrying inside the same failed commit context
try { table.updateSchema()...commit(); } catch (CommitFailedException e) { /* uncertain */ }
// after: reload and re-apply on UNKNOWN status
Table reloaded = catalog.loadTable(identifier);
reloaded.updateSchema().addColumn("new_col", Types.LongType.get()).commit();
Defensive patterns

Strategy: retry

Validate before calling

// before committing, check current metadata location matches your last-read state
TableMetadata current = ((HasTableOperations) table).operations().current();
boolean stillCurrent = current.metadataFileLocation().equals(lastSeenMetadataLocation);

Try / catch

try { table.refresh(); /* reapply changes */ table.updateSpec()...commit(); } catch (CommitFailedException e) { // reload table and reapply from scratch }

Prevention

When it happens

Trigger: checkCommitStatus is invoked after a commit exception; checkCommitStatusStrict determined FAILURE because the metadata location in the metastore is different and newMetadataLocation is absent from the version history stored in the 'previous-versions'/'metadata-log' properties.

Common situations: Concurrent writers where another client committed a different snapshot before this commit; Hive/Glue/Nessie metastores where commit racing is common; network timeouts during commit causing retry logic to run the status check.

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