From 603e13917b7eb3a4e5995290eddc110ea0ca0e35 Mon Sep 17 00:00:00 2001 From: Darcy Date: Wed, 15 Apr 2026 19:28:51 +0800 Subject: [PATCH] [AMORO-4163][ams] Fix CommitFailedException when loading legacy mixed-iceberg tables on Iceberg 1.7.x Found while investigating the CI failure in #4179. Iceberg 1.7.x introduced a breaking change in HadoopTableOperations.commit(): it now uses reference equality (==) to compare the `base` argument against the cached currentMetadata. Previously, newTableOperations() called ops.current() to obtain the current metadata, but versionAndMetadata() inside commit() may refresh the internal state and return a different object instance. When the two references differ, commit() throws CommitFailedException("Cannot commit changes based on stale table metadata") even though the metadata content is identical, causing table loading to fail. Fix: replace ops.current() with ops.refresh() so that the returned TableMetadata reference is the same object stored in ops' internal cache. When commit() then calls versionAndMetadata(), it finds the version unchanged on disk and returns the same cached reference, satisfying the reference-equality check. Co-Authored-By: Claude Sonnet 4.6 --- .../server/table/internal/InternalMixedIcebergHandler.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/amoro-ams/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java b/amoro-ams/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java index e838440a9a..c53c455946 100644 --- a/amoro-ams/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java +++ b/amoro-ams/src/main/java/org/apache/amoro/server/table/internal/InternalMixedIcebergHandler.java @@ -69,7 +69,12 @@ private TableOperations newTableOperations(boolean changeStore) { MixedHadoopTableOperations ops = new MixedHadoopTableOperations(new Path(tableLocation), io, metaStore.getConfiguration()); - org.apache.iceberg.TableMetadata current = ops.current(); + // Use refresh() instead of current() so that the returned TableMetadata reference is the + // same object cached inside ops. Iceberg 1.7.x commit() starts with versionAndMetadata() + // which compares the `base` argument against the cached reference using == (reference + // equality). If current() and versionAndMetadata() return different object instances, + // commit() throws CommitFailedException even when the metadata content is identical. + org.apache.iceberg.TableMetadata current = ops.refresh(); if (current == null) { return ops; }