You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Upsert fails after update_schema().union_by_name() due to schema mismatch #3105
When performing an upsert operation after adding a new column via update_schema().union_by_name() , the operation fails with a ValueError indicating that the schema field names don't match.
To reproduce:
frompyiceberg.catalogimportload_catalogimportpolarsasplcatalog=load_catalog("default", **{"type": "in-memory"})
df=pl.DataFrame(
[
{"id": 1, "name": "Alice", "age": 30, "city": "São Paulo"},
{"id": 2, "name": "Bob", "age": 25, "city": "Rio de Janeiro"},
{"id": 3, "name": "Carol", "age": 35, "city": "Belo Horizonte"},
{"id": 4, "name": "David", "age": 28, "city": "Curitiba"},
]
)
arrow=df.to_arrow()
catalog.create_namespace_if_not_exists("default")
catalog.create_table_if_not_exists("default.my_table", arrow.schema)
table=catalog.load_table("default.my_table")
try:
table.append(arrow)
# Add a new columnarrow=df.with_columns(ping=pl.lit("pong")).to_arrow()
# Update schema to include the new columnwithtable.update_schema() asupdate_schema:
update_schema.union_by_name(arrow.schema)
table=table.refresh()
# This fails with ValueErrortable.upsert(arrow, ["id"])
finally:
catalog.drop_table("default.my_table")
Error: ValueError: Target schema's field names are not matching the table's field names: ['id', 'name', 'age', 'city', 'ping'], ['id', 'name', 'age', 'city']
Stack trace:
File "pyiceberg/table/__init__.py", line 1343, in upsert
return tx.upsert(
File "pyiceberg/table/__init__.py", line 825, in upsert
rows_to_update = upsert_util.get_rows_to_update(df, rows, join_cols)
File "pyiceberg/table/upsert_util.py", line 92, in get_rows_to_update
source_table.cast(target_table.schema)
File "pyarrow/table.pxi", line 4721, in pyarrow.lib.Table.cast
Expected:
The upsert operation should succeed after the schema has been updated to include the new column.
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
Same issue with add_column, the issue stems from the get_rows_to_update in upsert_utils where the data is cast to the underlying table schema. Which fails since the schemas are different (pyarrow cast is not adding/deleting/reordering the columns).
This makes upsert unusable for the tables with updated schemas.
frompyiceberg.catalogimportload_catalogimportpolarsasplfrompyiceberg.typesimportStringTypecatalog=load_catalog("default", **{"type": "in-memory"})
df=pl.DataFrame(
[
{"id": 1, "name": "Alice", "age": 30, "city": "São Paulo"},
{"id": 2, "name": "Bob", "age": 25, "city": "Rio de Janeiro"},
{"id": 3, "name": "Carol", "age": 35, "city": "Belo Horizonte"},
{"id": 4, "name": "David", "age": 28, "city": "Curitiba"},
]
)
arrow=df.to_arrow()
catalog.create_namespace_if_not_exists("default")
catalog.create_table_if_not_exists("default.my_table", arrow.schema)
table=catalog.load_table("default.my_table")
table.append(arrow)
# Add a new columnarrow=df.with_columns(ping=pl.lit("pong")).to_arrow()
# Update schema to include the new columnwithtable.update_schema() asupdate_schema:
update_schema.add_column("ping", StringType())
table=table.refresh()
print(table.schema())
try:
# This fails with ValueErrortable.upsert(arrow, ["id"])
finally:
catalog.drop_table("default.my_table")
Hopefully I will create today a PR for resolving this basically these lines
Activity
laserninja commentedon Mar 25, 2026
Let me know if you need help fixing it.
AndrejIring commentedon Apr 30, 2026
Same issue with
add_column, the issue stems from theget_rows_to_updateinupsert_utilswhere the data is cast to the underlying table schema. Which fails since the schemas are different (pyarrowcast is not adding/deleting/reordering the columns).This makes
upsertunusable for the tables with updated schemas.Hopefully I will create today a PR for resolving this basically these lines
iceberg-python/pyiceberg/table/upsert_util.py
Lines 91 to 95 in b67b724
Currently working workaround is to use
table.overwriteafter the schema evolution, to update the underlying tables.Example of the workaround:
clifflau1120 commentedon May 22, 2026
This is a real issue. This implies full rewrite whenever we add a column during schema evolution. This goes against the whole idea of Apache Iceberg.
fix(dlt): commit a snapshot under the new schema before Iceberg upser…