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

  1. Keep only snapshot_id if you want one specific snapshot.
  2. Remove snapshot_id and keep the from/to bounds for a snapshot range read.
  3. 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

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


AI-assisted analysis of pola-rs/polars@68506541d2 (2026-09-10). Data as JSON: /api/errors/f22edb094ed8bc2e. Report an issue: GitHub.