pola-rs/polars · error

failed to load iceberg deletion vector: 'python' feature…

Error message

failed to load iceberg deletion vector: 'python' feature not enabled

What it means

Loading an Iceberg deletion vector (Puffin deletes) requires the 'python' feature for the deletion-vector loading path, and the non-python build panics explicitly. When the binary was compiled without feature = "python", load_iceberg_puffin_deletes cannot execute and aborts via panic!.

Solutions

  1. Rebuild Polars with the python feature enabled: cargo build --features python (or use the Python bindings, which enable it).
  2. Remove/rewrite the Iceberg deletes so the table has no puffin deletion vectors (e.g. rewrite/compact data files) if a python-less build must be used.
  3. Verify which feature set your binary was built with before scanning Iceberg tables with delete files.

Example fix

// before
cargo build --release
// after
cargo build --release --features python
Defensive patterns

Strategy: validation

Validate before calling

# Check your build has the required feature before scanning Iceberg tables with deletes
cargo metadata --format-version 1 | grep -q '"python"' && echo 'python feature present' || echo 'python feature MISSING - deletion vectors will panic'

Try / catch

try:
    df = pl.scan_iceberg(table).collect()
except Exception as e:
    if "'python' feature not enabled" in str(e):
        raise RuntimeError('Rebuild Polars with --features python to load Iceberg deletion vectors') from e
    raise

Prevention

When it happens

Trigger: Scanning an Iceberg table whose data files have puffin deletion vectors through a Polars build compiled without the 'python' feature (e.g. polars-cli or a cargo build without --features python).

Common situations: Users run the polars-cli or a custom Rust build against an Iceberg table with positional/mor deletes and hit the panic, while the Python bindings build (with python feature) works.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/3b273f0312e8923a. Report an issue: GitHub.

Appendix: source

Thrown at crates/polars-stream/src/nodes/io_sources/multi_scan/components/row_deletions.rs:725

                Ok((data_path, mask))
            })
            .collect();

        static LOAD_FROM_BYTES_FN: LazyLock<Py<PyAny>> = LazyLock::new(|| {
            Python::attach(|py| {
                use pyo3::types::PyAnyMethods;

                py.import("polars.io.iceberg._utils")
                    .unwrap()
                    .getattr("load_puffin_deletion_file")
                    .unwrap()
                    .unbind()
            })
        });
    }
    #[cfg(not(feature = "python"))]
    {
        panic!("failed to load iceberg deletion vector: 'python' feature not enabled")
    }
}

#[cfg(test)]
mod tests {
    use polars_utils::slice_enum::Slice;

    use super::ExternalFilterMask;

    fn split_mask<I>(mask: I, slice: Slice) -> (Vec<bool>, Slice)
    where
        I: IntoIterator<Item = bool>,
    {
        let mask = ExternalFilterMask::Iceberg {
            mask: mask.into_iter().collect(),
        };

        let slice = mask.calc_physical_slice(slice);

View on GitHub (pinned to fe841f959e)