Core: Discard changes when suppressing historical snapshots in CatalogHandlers
Maintainer thường phản hồi trong vòng 1 ngày
@ebyhr đang làm issue này rồi.
Từ ngày 27/8/2026.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 78/100
Hướng nghiên cứu
Bắt đầu trong core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java tại loadTable và nhánh snapshot-loading-mode=refs của nó; so sánh việc xây dựng lại metadata với RESTSessionCatalog.loadTable. Tái hiện lỗi thông qua RESTCatalogAdapter bằng cách sử dụng một snapshot lịch sử có tệp thống kê, sau đó xác minh rằng GET .../tables/{table}?snapshots=refs thành công mà không gặp metadata-location exception.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Apache Iceberg version
1.11.0 (latest release)
Query engine
None
Please describe the bug 🐞
Behavior
In snapshot-loading-mode=refs, CatalogHandlers.loadTable fails with IllegalArgumentException: Cannot set metadata location with changes to table metadata: 1 changes when serving GET .../tables/{table}?snapshots=refs for a table that has a statistics file (or partition statistics file) attached to a historical (unreferenced) snapshot.
Cause
The REFS branch builds the response metadata like this (CatalogHandlers.java#L526-L531):
metadata =
TableMetadata.buildFrom(loadedMetadata)
.withMetadataLocation(loadedMetadata.metadataFileLocation())
.suppressHistoricalSnapshots()
.build();
suppressHistoricalSnapshots() does not record RemoveSnapshots changes, but it removes the suppressed snapshots' statistics via removeStatistics(...) / removePartitionStatistics(...), which do record MetadataUpdate.RemoveStatistics / RemovePartitionStatistics changes (TableMetadata.java, rewriteSnapshotsInternal). build() then rejects the combination of pending changes and a set metadata location.
The client-side equivalent in RESTSessionCatalog.loadTable already prevents this with by calling .discardChanges() when rebuilding metadata; CatalogHandlers performs the change-recording suppression without that measure.
To Reproduce
E.g. via RESTCatalogAdapter with snapshot-loading-mode=refs on the client:
- Create a table, commit snapshot A, attach a
StatisticsFileto A (e.g.UpdateStatistics). - Commit snapshot B so A becomes historical (only reachable via parent chain, not via refs).
loadTablewithsnapshots=refs→ 500 /IllegalArgumentException: Cannot set metadata location with changes to table metadata: 1 changes.
Encountered in practice testing Trino's REST catalog against the in-memory test server with snapshot-loading-mode=refs: Trino writes statistics on INSERT by default, so the first loadTable after a stats-bearing snapshot becomes historical reliably fails.
Suggested Fix
Add .discardChanges() to the builder chain in CatalogHandlers.loadTable (matching the client-side wrapper), e.g.
TableMetadata.buildFrom(loadedMetadata)
.withMetadataLocation(loadedMetadata.metadataFileLocation())
.suppressHistoricalSnapshots()
.discardChanges()
.build();
This would be the minimal fix, keeping the general behavior as is. Alternatively, the suppress-parameter that already prevents MetadataUpdate.RemoveSnapshots changes from being created here could be incorporated into removeStatistics() and removePartitionStatistics() to prevent change creation there at the root.
AI assistance
Found this while working on a trino patch. This root-cause analysis was AI-assisted. I'm quite confident this is an actual bug and checked this in detail before opening the issue. I'll link to the related PR at trino shortly, whose test triggers this behavior.
Willingness to contribute
- I can contribute a fix for this bug independently
- I would be willing to contribute a fix for this bug with guidance from the Iceberg community
- I cannot contribute a fix for this bug at this time
- Ngôn ngữ chính
- Java
- Star
- 9.3k
- Fork
- 3.6k
- Merge trung bình
- 2 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 143
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của apache/iceberg
-
Kafka: Filter empty strings and whitespace in IcebergSinkConfig stringToListCó thể đã có người làm @mohamed-elbrik đã nhận hôm nay. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Parquet TIME_MILLIS statistics are not converted to microsecondsCó thể đã có người làm @chenjian2664 đã nhận 9 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Temporal transforms put pre-epoch timestamps at `.999999` into the previous unitCó thể đã có người làm @gitedmond đã nhận 16 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
apache/iceberg#18371 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
OpenAPI: Remove deprecated TrueExpression and FalseExpressionCó thể đã có người làm @zhang-arvin đã nhận 11 ngày trước. Đang mởimprovement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
apache/iceberg#18351 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Parquet: StringReader decodes every occurrence of a dictionary value into a new StringCó thể đã có người làm @Neuw84 đã nhận 25 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
apache/iceberg#18259 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của apache/iceberg
Issue tương tự
-
area: android good first issue help wanted testing
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Gautam-aman/ResQNet#56 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
documentation hermes-queue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
chrisalunlloyd2-sudo/mindpalace#294 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
better night vision compatĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
QuicksilverMC/Argentum#31 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
saysky/ForestBlog#111 ·
-
hawkbit-dmf-server 1.1.0 does not start: NoClassDefFoundError jakarta/servlet/ServletResponseĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
eclipse-hawkbit/hawkbit#3429 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày