pola-rs/polars · error
can't convert {pyseries.dtype()} to Decimal
Error message
can't convert {pyseries.dtype()} to Decimal What it means
When a Series must become Decimal (explicit dtype=pl.Decimal or a cast), polars only has conversion paths for strings (scale inferred), floats (via string to infer scale), integers/Null (scale 0). Every other dtype — Boolean, Date/Datetime, Categorical, List — has no defined decimal meaning and raises this TypeError.
Source
Thrown at py-polars/src/polars/_utils/construction/series.py:194
if pyseries.dtype() != dtype:
pyseries = pyseries.cast(dtype, strict=strict, wrap_numerical=False)
# Uninstanced Decimal is a bit special and has various inference paths
if dtype == Decimal:
if pyseries.dtype() == String:
pyseries = pyseries.str_to_decimal_infer(inference_length=0)
elif pyseries.dtype().is_float():
# Go through string so we infer an appropriate scale.
pyseries = pyseries.cast(
String, strict=strict, wrap_numerical=False
).str_to_decimal_infer(inference_length=0)
elif pyseries.dtype().is_integer() or pyseries.dtype() == Null:
pyseries = pyseries.cast(
Decimal(scale=0), strict=strict, wrap_numerical=False
)
elif not isinstance(pyseries.dtype(), Decimal):
msg = f"can't convert {pyseries.dtype()} to Decimal"
raise TypeError(msg)
return pyseries
elif dtype == Struct:
# This is very bad. Goes via rows? And needs to do outer nullability separate.
# It also has two data passes.
# TODO: eventually go into struct builder
struct_schema = dtype.to_schema() if isinstance(dtype, Struct) else None
empty = {} # type: ignore[var-annotated]
data = []
invalid = []
for i, v in enumerate(values):
if v is None:
invalid.append(i)
data.append(empty)
else:
data.append(v)View on GitHub (pinned to df599052da)
Solutions
- Cast to Int64 first: s.cast(pl.Int64).cast(pl.Decimal(precision, scale)).
- For booleans map to 0/1: s.cast(pl.Int8).cast(pl.Decimal).
- For text-based decimal values, go through String: pl.Series(s, dtype=pl.Decimal) infers scale from strings.
- Skip/guard non-numeric columns instead of blanket-casting the whole frame.
Example fix
// before s = pl.Series([True, False, True]).cast(pl.Decimal) // after s = pl.Series([True, False, True]).cast(pl.Int8).cast(pl.Decimal(10, 0))
Defensive patterns
Strategy: type-guard
Validate before calling
s = pl.Series(values)
if s.dtype not in (pl.String, pl.Null) and not (s.dtype.is_integer() or s.dtype.is_float()):
s = s.cast(pl.Int64) # or skip / raise for your domain
s = s.cast(pl.Decimal(precision, scale)) Type guard
def is_decimal_castable(dtype: pl.DataType) -> bool:
return dtype.is_integer() or dtype.is_float() or dtype in (pl.String, pl.Null) Try / catch
try:
out = s.cast(pl.Decimal(38, 10))
except TypeError as e:
if "to Decimal" in str(e):
out = s.cast(pl.Int64).cast(pl.Decimal(38, 10))
else:
raise Prevention
- Whitelist dtypes before blanket Decimal casts.
- Convert booleans/temporals to integers explicitly in your mapping layer.
- Keep money columns as strings at ingestion so scale inference is deterministic.
When it happens
Trigger: pl.Series([True, False]).cast(pl.Decimal); pl.Series([date(2020,1,1)]).cast(pl.Decimal); pl.Series("d", [True], dtype=pl.Decimal).
Common situations: Financial pipelines casting every numeric-looking column to Decimal where a column turned out boolean/temporal; schema drift after an upstream change; blanket .cast(pl.Decimal(precision, scale)) over all columns.
Related errors
- cannot select columns using Series of type {dtype}
- cannot compare datetime.datetime to Series of type {self.dty
- cannot do arithmetic with Series of dtype: {self.dtype!r} an
- first cast to integer before dividing datelike dtypes
- first cast to integer before multiplying datelike dtypes
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/07d9a0110db379b4.
Report an issue: GitHub.