pola-rs/polars · error · NotImplementedError
sink to Iceberg table with partition field '{field.name}' on
Error message
sink to Iceberg table with partition field '{field.name}' on source column '{source_name}' with '{metrics_mode}' metrics; partition value inference requires lower and upper bounds What it means
The Iceberg sink derives partition values from Parquet lower/upper bound statistics. This error means the partition field's source column was written with a metrics mode (e.g. `none` or truncated metrics) that omits the lower/upper bounds needed to infer the partition value. It is raised as NotImplementedError because the sink does not support that configuration combination.
Source
Thrown at py-polars/src/polars/io/iceberg/_sink.py:290
exprs: list[pl.Expr] = []
for field in spec.fields:
source_field = schema.find_field(field.source_id)
statistics = statistics_plan.get(field.source_id)
if field.source_id not in nested_source_ids and (
statistics is None or statistics.mode.type not in bounds_metrics_modes
):
source_name = schema.find_column_name(field.source_id)
metrics_mode = (
statistics.mode.type.value if statistics is not None else "unavailable"
)
msg = (
"sink to Iceberg table with partition field "
f"'{field.name}' on source column '{source_name}' with "
f"'{metrics_mode}' metrics; partition value inference requires "
"lower and upper bounds"
)
raise NotImplementedError(msg)
source_type = source_field.field_type
transform = field.transform
expr = _partition_source_expr(schema, field.source_id)
if isinstance(transform, IdentityTransform):
pass
elif isinstance(
transform, (YearTransform, MonthTransform, DayTransform, HourTransform)
):
if type(source_type).__name__ in {
"TimestamptzType",
"TimestamptzNanoType",
}:
expr = expr.dt.convert_time_zone("UTC")
if isinstance(transform, YearTransform):
expr = expr.dt.year() - 1970View on GitHub (pinned to fc24390824)
Solutions
- Change the table property so the partition source column collects full metrics: set `write.metrics.<column>=full` (or `write.metrics.default=truncate/full`) on the Iceberg table
- Recreate the table with default metrics (`full`/`truncate` at sufficient length) if you can control the schema/metadata
- Sink to a non-partitioned table, or pre-write the partition key as a top-level column with metrics enabled
- Check `table.properties` via pyiceberg before sinking to confirm the metric mode for the source column
Example fix
// before: metrics disabled for the partition source column table.properties['write.metrics.category'] = 'none' // after: require full metrics for the partition key column table.properties['write.metrics.category'] = 'full' lf.sink_iceberg(table)
Defensive patterns
Strategy: validation
Validate before calling
for field in table.spec().fields:
col = table.metadata.current_schema.find_field(field.source_id).name
mode = table.properties.get(f'write.metrics.{col}', table.properties.get('write.metrics.default', 'truncate'))
if mode == 'none':
raise ValueError(f"metrics mode '{mode}' for partition source column '{col}' prevents partition value inference") Type guard
def metrics_allow_bounds(table, source_name: str) -> bool:
mode = table.properties.get(f'write.metrics.{source_name}', table.properties.get('write.metrics.default'))
return mode != 'none' Try / catch
try:
lf.sink_iceberg(table)
except NotImplementedError as e:
if 'partition value inference requires lower and upper bounds' in str(e):
raise RuntimeError("set write.metrics.<partition_col>=full on the table before sinking") from e
raise Prevention
- Audit `table.properties` for write.metrics.* settings, especially per-column overrides on partition key columns
- Avoid `write.metrics.default=none` on tables you intend to sink to with polars
- Set `write.metrics.<column>=full` for every partition source column
When it happens
Trigger: Sinking to a partitioned Iceberg table when the table's metrics config (`write.metrics.default` / per-column `write.metrics.<column>`) for the partition source column is set to a mode without min/max bounds (e.g. `none`), while partition value inference is required.
Common situations: Tables created with `write.metrics.default=none` for performance; per-column metrics tuned down for wide tables accidentally applied to a partition key column; inheriting a table created by another engine with restrictive metrics settings.
Related errors
- partition source field {source_id} has non-struct parent
- Cannot infer partition value from Parquet metadata for parti
- sink to Iceberg table with '{transform}' partition transform
- sink to Iceberg table with '{transform}' partition transform
- schema_mode='overwrite' is not supported for partitioned Ice
AI-assisted analysis of pola-rs/polars@fc24390824 (2026-09-02).
Data as JSON: /api/errors/2b8fc70fe615abae.
Report an issue: GitHub.