apache/iceberg · error · CommitFailedException

Replace failed, E-Tag

Error message

Replace failed, E-Tag %s mismatch for table %s

What it means

CommitFailedException thrown by EcsTableOperations.doCommit when an optimistic-concurrency replace of the properties object fails because the cached E-Tag no longer matches, meaning another writer updated the table between refresh and commit.

Solutions

  1. Retry the operation: reload the table (refresh picks up the new state) and re-apply the commit; Iceberg retries CommitFailedException automatically in most engines
  2. Call table.refresh() before committing to reduce stale E-Tag windows
  3. Check for competing writers to the same table

Example fix

// before
table.updateSchema().addColumn("c", Types.LongType.get()).commit(); // stale reference
// after
table.refresh();
table.updateSchema().addColumn("c", Types.LongType.get()).commit();
Defensive patterns

Strategy: retry

Try / catch

try { table.refresh(); table.update...().commit(); } catch (CommitFailedException e) { table.refresh(); /* retry commit with fresh E-Tag */ }

Prevention

When it happens

Trigger: Committing table updates (base != null) when updatePropertiesObject returns false because the stored object's E-Tag differs from the cachedETag captured at load/refresh time.

Common situations: Two concurrent writers committing to the same table (common in Spark with multiple tasks/executors), a concurrent drop-and-recreate, or refresh not called before commit.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at dell/src/main/java/org/apache/iceberg/dell/ecs/EcsTableOperations.java:105

  @Override
  protected void doCommit(TableMetadata base, TableMetadata metadata) {
    boolean newTable = base == null;
    String newMetadataLocation = writeNewMetadataIfRequired(newTable, metadata);
    if (base == null) {
      // create a new table, the metadataKey should be absent
      if (!catalog.putNewProperties(tableObject, buildProperties(newMetadataLocation))) {
        throw new CommitFailedException("Table is existing when create table %s", tableName());
      }
    } else {
      String cachedETag = eTag;
      Preconditions.checkNotNull(cachedETag, "E-Tag must be not null when update table");
      // replace to a new version, the E-Tag should be present and matched
      boolean result =
          catalog.updatePropertiesObject(
              tableObject, cachedETag, buildProperties(newMetadataLocation));
      if (!result) {
        throw new CommitFailedException(
            "Replace failed, E-Tag %s mismatch for table %s", cachedETag, tableName());
      }
    }
  }

  /** Build properties for table */
  private Map<String, String> buildProperties(String metadataLocation) {
    return ImmutableMap.of(ICEBERG_METADATA_LOCATION, metadataLocation);
  }
}

View on GitHub (pinned to 86d9c8fc54)