{"record":{"id":"07d9a0110db379b4","repo":"pola-rs/polars","slug":"can-t-convert-pyseries-dtype-to-decimal","errorCode":null,"errorMessage":"can't convert {pyseries.dtype()} to Decimal","messagePattern":"can't convert (.+?) to Decimal","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/_utils/construction/series.py","lineNumber":194,"sourceCode":"            if pyseries.dtype() != dtype:\n                pyseries = pyseries.cast(dtype, strict=strict, wrap_numerical=False)\n\n        # Uninstanced Decimal is a bit special and has various inference paths\n        if dtype == Decimal:\n            if pyseries.dtype() == String:\n                pyseries = pyseries.str_to_decimal_infer(inference_length=0)\n            elif pyseries.dtype().is_float():\n                # Go through string so we infer an appropriate scale.\n                pyseries = pyseries.cast(\n                    String, strict=strict, wrap_numerical=False\n                ).str_to_decimal_infer(inference_length=0)\n            elif pyseries.dtype().is_integer() or pyseries.dtype() == Null:\n                pyseries = pyseries.cast(\n                    Decimal(scale=0), strict=strict, wrap_numerical=False\n                )\n            elif not isinstance(pyseries.dtype(), Decimal):\n                msg = f\"can't convert {pyseries.dtype()} to Decimal\"\n                raise TypeError(msg)\n\n        return pyseries\n\n    elif dtype == Struct:\n        # This is very bad. Goes via rows? And needs to do outer nullability separate.\n        # It also has two data passes.\n        # TODO: eventually go into struct builder\n        struct_schema = dtype.to_schema() if isinstance(dtype, Struct) else None\n        empty = {}  # type: ignore[var-annotated]\n\n        data = []\n        invalid = []\n        for i, v in enumerate(values):\n            if v is None:\n                invalid.append(i)\n                data.append(empty)\n            else:\n                data.append(v)","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/_utils/construction/series.py#L176-L212","documentation":"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.","triggerScenarios":"pl.Series([True, False]).cast(pl.Decimal); pl.Series([date(2020,1,1)]).cast(pl.Decimal); pl.Series(\"d\", [True], dtype=pl.Decimal).","commonSituations":"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.","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."],"exampleFix":"// before\ns = pl.Series([True, False, True]).cast(pl.Decimal)\n\n// after\ns = pl.Series([True, False, True]).cast(pl.Int8).cast(pl.Decimal(10, 0))","handlingStrategy":"type-guard","validationCode":"s = pl.Series(values)\nif s.dtype not in (pl.String, pl.Null) and not (s.dtype.is_integer() or s.dtype.is_float()):\n    s = s.cast(pl.Int64)  # or skip / raise for your domain\ns = s.cast(pl.Decimal(precision, scale))","typeGuard":"def is_decimal_castable(dtype: pl.DataType) -> bool:\n    return dtype.is_integer() or dtype.is_float() or dtype in (pl.String, pl.Null)","tryCatchPattern":"try:\n    out = s.cast(pl.Decimal(38, 10))\nexcept TypeError as e:\n    if \"to Decimal\" in str(e):\n        out = s.cast(pl.Int64).cast(pl.Decimal(38, 10))\n    else:\n        raise","preventionTips":["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."],"tags":["decimal","cast","dtype","series"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}