pola-rs/polars · error · TypeError

dtypes must be fully-specified, got: {tp!r}

Error message

dtypes must be fully-specified, got: {tp!r}

What it means

pl.Schema validates dtypes: simple dtype classes (pl.Int64, pl.String) are auto-instantiated, but nested/parametric types (List, Struct, Array, Enum, Decimal) must be fully specified because they require constructor args. Passing a bare parametric class raises TypeError.

Source

Thrown at py-polars/src/polars/schema.py:56

    from polars._dependencies import pyarrow as pa


def _required_init_args(tp: DataTypeClass) -> bool:
    return bool(tp.__annotations__)


BaseSchema = OrderedDict[str, DataType]
SchemaInitDataType: TypeAlias = DataType | DataTypeClass | PythonDataType

__all__ = ["Schema"]


def _check_dtype(tp: DataType | DataTypeClass) -> DataType:
    if not isinstance(tp, DataType):
        # note: if nested/decimal, or has signature params, this implies required args
        if tp.is_nested() or tp.is_decimal() or _required_init_args(tp):
            msg = f"dtypes must be fully-specified, got: {tp!r}"
            raise TypeError(msg)
        tp = tp()
    return tp  # type: ignore[return-value]


def _is_arrow_schema_exportable(obj: Any) -> TypeIs[ArrowSchemaExportable]:
    return hasattr(obj, "__arrow_c_schema__")


class Schema(BaseSchema):
    """
    Ordered mapping of column names to their data type.

    Parameters
    ----------
    schema
        The schema definition given by column names and their associated
        Polars data type. Accepts a mapping, or an iterable of tuples, or any
        object implementing the  `__arrow_c_schema__` PyCapsule interface

View on GitHub (pinned to df599052da)

Solutions

  1. Fully instantiate the dtype: pl.List(pl.Int64), pl.Array(pl.Int64, 3), pl.Enum(['a','b']), pl.Decimal(38, 10)
  2. Copy real instances from df.schema rather than re-typing classes
  3. As a last resort construct with check_dtypes=False (skips validation, stores the bare class - only if downstream tolerates it)

Example fix

# before
pl.Schema({'a': pl.List})

# after
pl.Schema({'a': pl.List(pl.Int64)})
Defensive patterns

Strategy: type-guard

Validate before calling

from polars.datatypes import is_polars_dtype

def fully_specified(tp) -> bool:
    return (
        isinstance(tp, DataTypeInstance := __import__('polars').DataType)
        or not (tp.is_nested() or tp.is_decimal())
    ) if is_polars_dtype(tp, include_unknown=True) else False

Type guard

import polars as pl
from polars._utils.parse import _required_init_args

def is_fully_specified_dtype(tp) -> bool:
    if isinstance(tp, pl.DataType):
        return True  # instance: already parameterized
    return not (tp.is_nested() or tp.is_decimal() or _required_init_args(tp))

Prevention

When it happens

Trigger: pl.Schema({'a': pl.List}), pl.Schema({'a': pl.Array}), pl.Schema({'a': pl.Enum}), pl.Schema({'a': pl.Decimal}); building schemas programmatically from classes instead of instances.

Common situations: Hand-written schema fixtures/config; copying a dtype CLASS from docs or type annotations (e.g. pl.List instead of pl.List(pl.Int64)); extracting type(x) instead of the instance.

Related errors


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