pola-rs/polars · error · TypeError

`compat_level` has invalid type: {qualified_type_name(compat

Error message

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

What it means

Inside the local `sink_ipc` implementation (engine.py:628) the `compat_level` argument is normalized: `None` means 'latest supported', a `polars.CompatLevel` instance supplies its pinned version, and anything else raises this TypeError. The check happens before the sink options are built, so the query never starts. Valid values are `None`, `pl.CompatLevel.newest`, or `pl.CompatLevel.oldest` (instances, not strings).

Source

Thrown at py-polars/src/polars/lazyframe/engine.py:628

        from polars.io.partition import _SinkOptions

        storage_options = _apply_retries_deprecation(retries, storage_options)

        credential_provider_builder = _init_credential_provider_builder(
            credential_provider, path, storage_options, "sink_ipc"
        )
        del credential_provider

        target = _to_sink_target(path)

        compat_level_py: int | bool
        if compat_level is None:
            compat_level_py = True
        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)

        if compression is None:
            compression = "uncompressed"

        sink_options = _SinkOptions(
            mkdir=mkdir,
            maintain_order=maintain_order,
            sync_on_close=sync_on_close,
            storage_options=storage_options,
            credential_provider=credential_provider_builder,
            sinked_paths_callback=sinked_paths_callback,
        )

        ldf_py = lf._ldf.sink_ipc(
            target=target,
            sink_options=sink_options,
            compression=compression,
            compat_level=compat_level_py,

View on GitHub (pinned to df599052da)

Solutions

  1. Pass `compat_level=None` (default, newest) or an explicit instance: `pl.CompatLevel.newest` / `pl.CompatLevel.oldest`
  2. If the value comes from config, map it first: `{'newest': pl.CompatLevel.newest, 'oldest': pl.CompatLevel.oldest}[value]`
  3. Validate with `isinstance(compat_level, (type(None), pl.CompatLevel))` before calling

Example fix

# before
lf.sink_ipc('out.arrow', compat_level='newest')  # TypeError

# after
lf.sink_ipc('out.arrow', compat_level=pl.CompatLevel.newest)
# or simply omit it (defaults to None/newest)
Defensive patterns

Strategy: type-guard

Validate before calling

import polars as pl

def normalize_compat_level(value):
    if value is None or isinstance(value, pl.CompatLevel):
        return value
    return {'newest': pl.CompatLevel.newest, 'oldest': pl.CompatLevel.oldest}[value]

lf.sink_ipc('out.arrow', compat_level=normalize_compat_level(cfg['compat_level']))

Type guard

from typing import TypeGuard
import polars as pl

def is_compat_level(value: object) -> TypeGuard[pl.CompatLevel | None]:
    return value is None or isinstance(value, pl.CompatLevel)

Try / catch

try:
    lf.sink_ipc('out.arrow', compat_level=compat_level)
except TypeError as e:
    if 'compat_level' in str(e):
        lf.sink_ipc('out.arrow')  # retry with default (newest)
    else:
        raise

Prevention

When it happens

Trigger: `lf.sink_ipc('out.arrow', compat_level='newest')`, `compat_level=0`/`compat_level=True`, or any non-`CompatLevel` object. The same wrong values work as strings elsewhere in some libraries, which misleads users.

Common situations: Copy-pasting configuration from code that stores compat levels as strings (e.g. YAML/JSON settings); passing an int version number learned from the Arrow IPC format docs; older snippets that predate the `CompatLevel` type passing booleans.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/d7860bac4b1ba969. Report an issue: GitHub.