pola-rs/polars · error · TypeError

`compat_level` has invalid type

Error message

`compat_level` has invalid type: {qualified_type_name(compat_level)!r}

What it means

Type discrimination on the `compat_level` argument to Series.to_arrow. The parameter accepts only None (meaning 'use defaults', mapped to False) or a CompatLevel instance (whose internal version number is extracted); any other type falls into the else branch and is rejected, with the qualified type name reported so the caller can see what was actually passed.

Solutions

  1. Pass a CompatLevel instance: pl.CompatLevel.oldest() or pl.CompatLevel.newest()
  2. Omit the argument (default None) if no specific compat level is needed
  3. Check the signature in your polars version; older versions have no compat_level param

Example fix

// before
srs.to_arrow(compat_level="oldest")
// after
srs.to_arrow(compat_level=pl.CompatLevel.oldest())
Defensive patterns

Strategy: type-guard

Validate before calling

assert compat_level is None or isinstance(compat_level, pl.CompatLevel), 'compat_level must be None or pl.CompatLevel'

Type guard

def valid_compat_level(cl) -> bool:
    return cl is None or isinstance(cl, pl.CompatLevel)

Try / catch

try:
    tbl = srs.to_arrow(compat_level=compat_level)
except TypeError:
    tbl = srs.to_arrow()

Prevention

When it happens

Trigger: srs.to_arrow(compat_level="oldest") or to_arrow(compat_level=1) instead of passing pl.CompatLevel.oldest() / pl.CompatLevel.newest().

Common situations: Copying API style from to_pandas/use_pyarrow options; guessing that compat_level takes a string like other polars options.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at py-polars/src/polars/series/series.py:5231

        --------
        >>> s = pl.Series("a", [1, 2, 3])
        >>> s = s.to_arrow()
        >>> s
        <pyarrow.lib.Int64Array object at ...>
        [
          1,
          2,
          3
        ]
        """
        compat_level_py: int | bool
        if compat_level is None:
            compat_level_py = False
        elif isinstance(compat_level, CompatLevel):
            compat_level_py = compat_level._version
        else:
            msg = f"`compat_level` has invalid type: {qualified_type_name(compat_level)!r}"
            raise TypeError(msg)
        return self._s.to_arrow(compat_level_py)

    def to_pandas(
        self, *, use_pyarrow_extension_array: bool = False, **kwargs: Any
    ) -> pd.Series[Any]:
        """
        Convert this Series to a pandas Series.

        This operation copies data if `use_pyarrow_extension_array` is not enabled.

        Parameters
        ----------
        use_pyarrow_extension_array
            Use a PyArrow-backed extension array instead of a NumPy array for the pandas
            Series. This allows zero copy operations and preservation of null values.
            Subsequent operations on the resulting pandas Series may trigger conversion
            to NumPy if those operations are not supported by PyArrow compute functions.
        **kwargs

View on GitHub (pinned to fe841f959e)