{"record":{"id":"d7860bac4b1ba969","repo":"pola-rs/polars","slug":"compat-level-has-invalid-type-qualified-type-n","errorCode":null,"errorMessage":"`compat_level` has invalid type: {qualified_type_name(compat_level)!r}","messagePattern":"`compat_level` has invalid type: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/lazyframe/engine.py","lineNumber":628,"sourceCode":"        from polars.io.partition import _SinkOptions\n\n        storage_options = _apply_retries_deprecation(retries, storage_options)\n\n        credential_provider_builder = _init_credential_provider_builder(\n            credential_provider, path, storage_options, \"sink_ipc\"\n        )\n        del credential_provider\n\n        target = _to_sink_target(path)\n\n        compat_level_py: int | bool\n        if compat_level is None:\n            compat_level_py = True\n        elif isinstance(compat_level, CompatLevel):\n            compat_level_py = compat_level._version\n        else:\n            msg = f\"`compat_level` has invalid type: {qualified_type_name(compat_level)!r}\"\n            raise TypeError(msg)\n\n        if compression is None:\n            compression = \"uncompressed\"\n\n        sink_options = _SinkOptions(\n            mkdir=mkdir,\n            maintain_order=maintain_order,\n            sync_on_close=sync_on_close,\n            storage_options=storage_options,\n            credential_provider=credential_provider_builder,\n            sinked_paths_callback=sinked_paths_callback,\n        )\n\n        ldf_py = lf._ldf.sink_ipc(\n            target=target,\n            sink_options=sink_options,\n            compression=compression,\n            compat_level=compat_level_py,","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/lazyframe/engine.py#L610-L646","documentation":"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).","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Pass `compat_level=None` (default, newest) or an explicit instance: `pl.CompatLevel.newest` / `pl.CompatLevel.oldest`","If the value comes from config, map it first: `{'newest': pl.CompatLevel.newest, 'oldest': pl.CompatLevel.oldest}[value]`","Validate with `isinstance(compat_level, (type(None), pl.CompatLevel))` before calling"],"exampleFix":"# before\nlf.sink_ipc('out.arrow', compat_level='newest')  # TypeError\n\n# after\nlf.sink_ipc('out.arrow', compat_level=pl.CompatLevel.newest)\n# or simply omit it (defaults to None/newest)","handlingStrategy":"type-guard","validationCode":"import polars as pl\n\ndef normalize_compat_level(value):\n    if value is None or isinstance(value, pl.CompatLevel):\n        return value\n    return {'newest': pl.CompatLevel.newest, 'oldest': pl.CompatLevel.oldest}[value]\n\nlf.sink_ipc('out.arrow', compat_level=normalize_compat_level(cfg['compat_level']))","typeGuard":"from typing import TypeGuard\nimport polars as pl\n\ndef is_compat_level(value: object) -> TypeGuard[pl.CompatLevel | None]:\n    return value is None or isinstance(value, pl.CompatLevel)","tryCatchPattern":"try:\n    lf.sink_ipc('out.arrow', compat_level=compat_level)\nexcept TypeError as e:\n    if 'compat_level' in str(e):\n        lf.sink_ipc('out.arrow')  # retry with default (newest)\n    else:\n        raise","preventionTips":["Always pass pl.CompatLevel instances (or None), never strings or ints","Map config strings to CompatLevel objects at the configuration boundary","Pin the compat level explicitly for files that must stay readable by older readers"],"tags":["polars","ipc","sink","compat-level","typeerror"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}