table.inspect metadata tables silently drop (or misattribute) partition values after a partition field rename
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 35/100
Research direction
Start with TableMetadata.specs_struct() and the inspect code that builds partition dicts from each file's historical PartitionSpec by field.name; key them by field_id instead. Run the reproduction script in the issue to see None values after the rename. Done when pre-rename partitions show {'p_renamed': 'a'} and {'p_renamed': 'b'} and the v1 remove/re-add case stays separate. Open PR #4363 already targets this, so check it before starting.
Written by the indexing model from the issue text.
Description
Apache Iceberg version
main (development)
Please describe the bug 🐞
Describe the bug
When a table evolves its partition spec by renaming a partition field:
TableMetadata.specs_struct()adopts the latest field name for that partitionfield_id(e.g.1000: p->1000: p_renamed).- However,
table.inspect.partitions(),files(),data_files(),all_files(),all_data_files(), andentries()build partition dictionaries usingfield.namefrom each file's historicalPartitionSpecdirectly ({"p": "a"}). - When PyArrow converts these rows to the schema defined by
specs_struct()(which has field"p_renamed"), the"p"key is ignored and"p_renamed"is filled withNone. All pre-rename partition values are silently replaced withNone({'p_renamed': None}).
Similarly, on format-version 1 tables, removing a partition field (remove_field("p")) and subsequently re-adding it (add_identity("p")) automatically renames the voided field (1000: p_1000) and creates 1001: p. Because inspect keys by historical field.name == "p", historical spec 0 data files written under field_id=1000 are silently misattributed to field_id=1001 ({'p_1000': None, 'p': 'a'}).
To Reproduce
import tempfile
import pyarrow as pa
from pyiceberg.catalog.memory import InMemoryCatalog
from pyiceberg.partitioning import PartitionField, PartitionSpec
from pyiceberg.schema import Schema
from pyiceberg.transforms import IdentityTransform
from pyiceberg.types import LongType, NestedField, StringType
with tempfile.TemporaryDirectory() as tmp:
cat = InMemoryCatalog("local", warehouse=f"file://{tmp}/wh")
cat.create_namespace("ns")
tbl = cat.create_table(
"ns.t_rename",
schema=Schema(NestedField(1, "id", LongType()), NestedField(2, "p", StringType())),
partition_spec=PartitionSpec(PartitionField(2, 1000, IdentityTransform(), "p")),
properties={"format-version": "2"},
)
tbl.append(pa.table({"id": [1, 2], "p": ["a", "b"]}))
tbl.update_spec().rename_field("p", "p_renamed").commit()
tbl.append(pa.table({"id": [3], "p": ["c"]}))
# Historical values 'a' and 'b' silently become None:
print(tbl.inspect.partitions().to_pydict()["partition"])
# Current output: [{'p_renamed': 'c'}, {'p_renamed': None}, {'p_renamed': None}]
# Expected output: [{'p_renamed': 'c'}, {'p_renamed': 'a'}, {'p_renamed': 'b'}]
print([r["partition"] for r in tbl.inspect.files().to_pylist()])
# Current output: [{'p_renamed': 'c'}, {'p_renamed': None}, {'p_renamed': None}]
# Expected output: [{'p_renamed': 'c'}, {'p_renamed': 'a'}, {'p_renamed': 'b'}]
Expected behavior
table.inspect tables should map partition field values using the canonical field names from specs_struct() based on field_id, preserving historical partition values across spec renames and correctly separating partition entries per specification layout.
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
- Dominant language
- Python
- Stars
- 1.2k
- Forks
- 664
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 131
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from apache/iceberg-python
-
StringLiteral to IntegerType/LongType silently truncates fractional strings, changing predicate meaningPossibly taken @Shahzeb-DataEngineer claimed this today. Openkind:bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
apache/iceberg-python#4382 · 2 comments ·
Maintainers usually reply within 1 day
-
`inspect.files()` and the other file metadata tables raise `ArrowInvalid` when a snapshot has no manifestsPossibly taken @YuangGao claimed this 12 days ago. Openkind:bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
apache/iceberg-python#4269 ·
Maintainers usually reply within 1 day
-
`inspect.entries()` raises TypeError when a data file has no column_sizesPossibly taken @Rahul-cs50 claimed this 16 days ago. Openkind:bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
apache/iceberg-python#4186 · 2 comments ·
Maintainers usually reply within 1 day
-
`older_than` reads a naive datetime as UTC and expires snapshots it should keepPossibly taken @Rahul-cs50 claimed this 15 days ago. Openkind:bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
apache/iceberg-python#4182 · 1 comment ·
Maintainers usually reply within 1 day
-
REST: Send empty first-page pageToken when rest-page-size is setPossibly taken @ehddnr301 claimed this 33 days ago. Openkind:bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
apache/iceberg-python#4096 ·
Maintainers usually reply within 1 day
All issues in apache/iceberg-python
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
peach-mitao/peach#693 ·
Maintainers usually reply within 1 day
-
FTP reads inside a transaction use a nonexistent staging pathPossibly taken @Harsh23Kashyap claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
fsspec/filesystem_spec#2463 ·
Maintainers usually reply within 1 day
-
comp/cli P2 tool/code-exec type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
NousResearch/hermes-agent#155989 ·
Maintainers usually reply within 1 day
-
PipesFileMessageReader parses a partially written message line: tail_file yields a line before its newline arrivesPossibly taken @PCTEJA claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
dagster-io/dagster#34442 ·
Maintainers usually reply within 1 day