pola-rs/polars · error · TypeError

dtype ' ' is a BaseExtension class, it should be an instance

Error message

dtype '{dtype}' is a BaseExtension class, it should be an instance

What it means

`pl.lit(dtype=...)` was given the extension dtype CLASS (e.g. a BaseExtension subclass) instead of an INSTANCE of it. Polars requires a concrete instance to know storage/extension metadata, so it refuses to construct a literal from the bare class.

Solutions

  1. Instantiate the extension dtype, e.g. pass `SomeExtensionDtype(...)` instead of `SomeExtensionDtype`
  2. If the dtype comes from config/registry, call it (with required args) before passing to pl.lit
  3. Check `isinstance(dtype, type)` at your call site and instantiate before calling pl.lit

Example fix

// before
pl.lit(1, dtype=pl.Categorical)
// after (for a custom extension dtype)
pl.lit(1, dtype=MyExtensionDtype())
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(dtype, type):
    dtype = dtype()  # instantiate extension dtype class
pl.lit(value, dtype=dtype)

Type guard

def is_dtype_instance(dtype) -> bool:
    return not isinstance(dtype, type)

Try / catch

try:
    expr = pl.lit(value, dtype=dtype)
except TypeError as e:
    if 'should be an instance' in str(e):
        expr = pl.lit(value, dtype=dtype())
    else:
        raise

Prevention

When it happens

Trigger: Calling `pl.lit(value, dtype=SomeExtensionDtype)` where `SomeExtensionDtype` is the class itself rather than `SomeExtensionDtype(...)`; commonly after an API change where extension dtypes switched from class-level to instance-level usage.

Common situations: Passing a dtype variable that holds the class from a factory/registry; forgetting parentheses on a parameterized extension dtype; migrating code from older polars versions that accepted classes.

Related errors


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

Appendix: source

Thrown at py-polars/src/polars/functions/lit.py:97

    >>> pl.lit(datetime(2023, 3, 31, 10, 30, 45))  # doctest: +IGNORE_RESULT

    Literal list/Series data (1D):

    >>> pl.lit([1, 2, 3])  # doctest: +SKIP
    >>> pl.lit(pl.Series("x", [1, 2, 3]))  # doctest: +IGNORE_RESULT

    Literal list/Series data (2D):

    >>> pl.lit([[1, 2], [3, 4]])  # doctest: +SKIP
    >>> pl.lit(pl.Series("y", [[1, 2], [3, 4]]))  # doctest: +IGNORE_RESULT
    """
    time_unit: TimeUnit

    if isinstance(dtype, BaseExtension):
        return lit(value, dtype.ext_storage()).ext.to(dtype)
    elif isinstance(dtype, type) and issubclass(dtype, BaseExtension):
        msg = f"dtype '{dtype}' is a BaseExtension class, it should be an instance"
        raise TypeError(msg)
    elif isinstance(dtype, DataTypeExpr):
        return lit(value).cast(dtype)
    elif dtype == Object:
        value_s = pl.Series("literal", [value], dtype=dtype)
        return wrap_expr(plr.lit(value_s._s, allow_object, is_scalar=True))
    elif dtype == Map:
        value_s = pl.Series("literal", [value], dtype=dtype)
        return wrap_expr(plr.lit(value_s._s, allow_object, is_scalar=True))
    elif dtype == Unknown:
        dtype = None

    if isinstance(value, datetime):
        if dtype == Date:
            return wrap_expr(plr.lit(value.date(), allow_object=False, is_scalar=True))

        # parse time unit
        if dtype is not None and (tu := getattr(dtype, "time_unit", "us")) is not None:
            tu = cast("TimeUnit", tu)

View on GitHub (pinned to fe841f959e)