pola-rs/polars · error · ValueError
cannot combine `snapshot_id` with `from_snapshot_id_exclusiv
Error message
cannot combine `snapshot_id` with `from_snapshot_id_exclusive` or `to_snapshot_id_inclusive`
What it means
scan_iceberg supports selecting snapshots either by a single `snapshot_id`, or by an exclusive lower bound and inclusive upper bound (`from_snapshot_id_exclusive` / `to_snapshot_id_inclusive`). Passing `snapshot_id` together with either bound is ambiguous, so a ValueError is raised before any table is loaded.
Source
Thrown at py-polars/src/polars/io/iceberg/functions.py:213
if reader_override is not None:
msg = "the `reader_override` parameter of `scan_iceberg()` is considered unstable."
issue_unstable_warning(msg)
if fast_deletion_count is not None:
msg = "the `fast_deletion_count` parameter of `scan_iceberg()` is considered unstable."
issue_unstable_warning(msg)
else:
fast_deletion_count = False
if snapshot_id is not None and (
from_snapshot_id_exclusive is not None or to_snapshot_id_inclusive is not None
):
msg = (
"cannot combine `snapshot_id` with `from_snapshot_id_exclusive` "
"or `to_snapshot_id_inclusive`"
)
raise ValueError(msg)
table: pyiceberg.table.Table | None = None
if importlib.util.find_spec("pyiceberg.table") is not None:
import pyiceberg.table
if isinstance(source, pyiceberg.table.Table):
table = source
table_descriptor_ = None
if table is None:
source = str(source)
table_descriptor_ = (
source # Inferred as static metadata path
if "/" in source or "\\" in source
else IcebergCatalogTableDescriptor(
table_identifier=source,View on GitHub (pinned to 68506541d2)
Solutions
- Keep only snapshot_id if you want one specific snapshot.
- Remove snapshot_id and keep the from/to bounds for a snapshot range read.
- If kwargs come from config/dict, filter out mutually exclusive keys before calling scan_iceberg.
Example fix
// before lf = pl.scan_iceberg(table, snapshot_id=42, to_snapshot_id_inclusive=99) // after lf = pl.scan_iceberg(table, to_snapshot_id_inclusive=99)
Defensive patterns
Strategy: validation
Validate before calling
def validate_iceberg_kwargs(kwargs):
if kwargs.get("snapshot_id") is not None and (
kwargs.get("from_snapshot_id_exclusive") is not None
or kwargs.get("to_snapshot_id_inclusive") is not None
):
raise ValueError("snapshot_id is mutually exclusive with from/to bounds")
return kwargs Try / catch
try:
lf = pl.scan_iceberg(source, **kwargs)
except ValueError as e:
if "cannot combine" in str(e):
kwargs.pop("snapshot_id", None)
lf = pl.scan_iceberg(source, **kwargs)
else:
raise Prevention
- Pick one snapshot-selection mode per call: id OR range, never both
- Filter mutually exclusive keys when building kwargs from config
- Centralize scan_iceberg argument construction in one helper
When it happens
Trigger: Calling pl.scan_iceberg(...) with snapshot_id set AND (from_snapshot_id_exclusive set OR to_snapshot_id_inclusive set).
Common situations: Refactoring code from single-snapshot reads to range reads (or vice versa) while leaving the old keyword in place; building kwargs dynamically from config where both keys end up populated.
Related errors
- schema_mode='overwrite' requires mode='overwrite'
- list.to_struct() got a str instead of a list. hint: pass ['{
- "pad_start" expects a `str`, given a {qualified_type_name(fi
- "pad_end" expects a `str`, given a {qualified_type_name(fill
- "extract_groups" expects a `str`, given a {qualified_type_na
AI-assisted analysis of pola-rs/polars@68506541d2 (2026-09-10).
Data as JSON: /api/errors/f22edb094ed8bc2e.
Report an issue: GitHub.