apache/iceberg · warning · CommitFailedException

Failed to update view

Error message

Failed to update view %s from catalog %s

What it means

updateView performs a conditional UPDATE of the view row (WHERE metadata_location = oldMetadataLocation) and expects exactly 1 updated row. If 0 (or more than 1) rows are updated, a CommitFailedException is thrown, meaning the expected prior state was not found or the update did not match exactly one view.

Solutions

  1. Refresh the view (viewOps.refresh()) to pick up the new metadata location and retry the commit
  2. Catch CommitFailedException and retry with backoff — this error is designed to be retried after re-reading state
  3. Check for duplicate rows in iceberg_views for the same catalog/namespace/view name and clean them up
  4. Verify the view was not dropped/recreated concurrently by another process
  5. Serialize writers per view or use an external lock if concurrent commits are routine

Example fix

// before: unconditional retry on same stale object
ops.commit(metadata, base); // fails repeatedly
// after: refresh between attempts
try {
  ops.commit(metadata, base);
} catch (CommitFailedException e) {
  ops.refresh();
  ops.commit(rebase(metadata), ops.current());
}
Defensive patterns

Strategy: retry

Validate before calling

// verify exactly one row exists for this view before updating
SELECT COUNT(*) FROM iceberg_views
WHERE catalog_name = ? AND view_namespace = ? AND view_name = ?; // expect 1

Try / catch

try {
  viewOps.commit(request);
} catch (CommitFailedException e) {
  viewOps.refresh();
  if (viewOps.current() != null) retryAsUpdate(); else retryAsCreate();
}

Prevention

When it happens

Trigger: Concurrent commit changed the metadata location between validateMetadataLocation and the UPDATE; the view row was deleted concurrently; the view row exists under a different catalog_name, so the conditional UPDATE matches nothing.

Common situations: Race between two writers committing the same view nearly simultaneously; view dropped by another process mid-commit; duplicated catalog rows from a manually seeded or corrupted catalog table.

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

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/jdbc/JdbcViewOperations.java:168

    String baseMetadataLocation = base != null ? base.metadataFileLocation() : null;

    if (!Objects.equals(baseMetadataLocation, catalogMetadataLocation)) {
      throw new CommitFailedException(
          "Cannot commit %s: metadata location %s has changed from %s",
          viewIdentifier, baseMetadataLocation, catalogMetadataLocation);
    }
  }

  private void updateView(String newMetadataLocation, String oldMetadataLocation)
      throws SQLException, InterruptedException {
    int updatedRecords =
        JdbcUtil.updateView(
            connections, catalogName, viewIdentifier, newMetadataLocation, oldMetadataLocation);

    if (updatedRecords == 1) {
      LOG.debug("Successfully committed to existing view: {}", viewIdentifier);
    } else {
      throw new CommitFailedException(
          "Failed to update view %s from catalog %s", viewIdentifier, catalogName);
    }
  }

  private void createView(String newMetadataLocation) throws SQLException, InterruptedException {
    Namespace namespace = viewIdentifier.namespace();
    if (PropertyUtil.propertyAsBoolean(catalogProperties, JdbcUtil.STRICT_MODE_PROPERTY, false)
        && !JdbcUtil.namespaceExists(catalogName, connections, namespace)) {
      throw new NoSuchNamespaceException(
          "Cannot create view %s in catalog %s. Namespace %s does not exist",
          viewIdentifier, catalogName, namespace);
    }

    if (JdbcUtil.tableExists(JdbcUtil.SchemaVersion.V1, catalogName, connections, viewIdentifier)) {
      throw new AlreadyExistsException("Table with same name already exists: %s", viewIdentifier);
    }

    if (JdbcUtil.viewExists(catalogName, connections, viewIdentifier)) {

View on GitHub (pinned to 86d9c8fc54)