pola-rs/polars · error · TypeError
cannot do arithmetic with Series of dtype
Error message
cannot do arithmetic with Series of dtype: {self.dtype!r} and argument of type: {type(other).__name__!r} What it means
_arithmetic dispatches +, -, *, /, % to a dtype-specific FFI function. When no implementation exists for the combination of the Series' dtype and the operand's Python type, it raises TypeError describing both sides. Polars does not silently coerce arbitrary type pairs for arithmetic; the user must cast explicitly.
Solutions
- Cast the operand or Series to a compatible dtype first, e.g. s.cast(pl.Int64) + 1 for numeric strings, or s.str.to_datetime() for date-like strings.
- For string concatenation, use explicit string APIs (s.str.concat / + between two Utf8 Series) — never Series + int.
- Rewrite as an expression for more flexible coercion: s.to_frame().select(pl.col(name) + other), which also gives clearer dtype errors.
- If mixing temporal and numeric types, cast the temporal column to Int64 first (s.cast(pl.Int64) or s.dt.epoch(...)) and re-cast afterwards.
Example fix
// before
s = pl.Series('n', ['1', '2', '3']) # dtype Utf8
s + 1 # TypeError: cannot do arithmetic with Series of dtype: String and argument of type: 'int'
// after
s.cast(pl.Int64) + 1 Defensive patterns
Strategy: validation
Validate before calling
NUMERIC = (pl.Int8, pl.Int16, pl.Int32, pl.Int64, pl.UInt8, pl.UInt16, pl.UInt32, pl.UInt64, pl.Float32, pl.Float64)
assert s.dtype in NUMERIC or not isinstance(other, (int, float)), \
f'cast operands to a numeric dtype before arithmetic (got {s.dtype} and {type(other).__name__})' Type guard
def arithmetic_compatible(dtype: pl.DataType, other) -> bool:
if isinstance(dtype, (pl.List, pl.Struct, pl.Object)):
return False
if dtype == pl.Utf8:
return isinstance(other, str) or (isinstance(other, pl.Series) and other.dtype == pl.Utf8)
return isinstance(other, (int, float, pl.Series)) Try / catch
try:
result = s + other
except TypeError as e:
if 'cannot do arithmetic with Series of dtype' in str(e):
result = s.cast(pl.Int64) + other # or str.to_datetime()/to_numeric() as appropriate
else:
raise Prevention
- Parse numeric columns explicitly after read_csv/read_parquet (schema overrides or str.to_numeric) so they are not Utf8.
- Use expression API (df.select(pl.col('x') + 1)) which coerces more flexibly and yields clearer errors.
- Never mix string and numeric operands; make concatenation vs addition explicit with str APIs or casts.
- Keep temporal and numeric arithmetic separate: cast temporal to Int64 before numeric ops.
- Unit-test arithmetic helpers with the dtypes your pipelines actually produce.
When it happens
Trigger: Applying +, -, *, / or % between a Series and an operand of an unsupported type, e.g. string_series + 1, int_series + 'abc', or arithmetic on List/Struct/Object-typed Series.
Common situations: Forgetting to parse numeric columns read from CSV (they stay Utf8/String, so 'col' + 1 fails); mixing string concatenation with numeric literals; passing datetimes or lists as operands instead of scalars or matching-dtype Series.
Related errors
- cannot compare datetime.datetime to Series of type
- cannot construct PySeries for type
- cannot convert DataFrame to
- cannot convert List column
- cannot convert Python type
AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18).
Data as JSON: /api/errors/5c7da5edd88c8f68.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/series/series.py:1085
if isinstance(other, int):
pyseries = sequence_to_pyseries(self.name, [other])
_s = self._from_pyseries(pyseries).cast(Decimal(scale=0))._s
else:
_s = sequence_to_pyseries(self.name, [other], dtype=Decimal)
if "rhs" in op_ffi:
return self._from_pyseries(getattr(_s, op_s)(self._s))
else:
return self._from_pyseries(getattr(self._s, op_s)(_s))
else:
other = maybe_cast(other, self.dtype)
f = get_ffi_func(op_ffi, self.dtype, self._s)
if f is None:
msg = (
f"cannot do arithmetic with Series of dtype: {self.dtype!r} and argument"
f" of type: {type(other).__name__!r}"
)
raise TypeError(msg)
return self._from_pyseries(f(other))
@overload
def __add__(self, other: DataFrame) -> DataFrame: ...
@overload
def __add__(self, other: Expr) -> Expr: ...
@overload
def __add__(self, other: Any) -> Self: ...
def __add__(self, other: Any) -> Series | DataFrame | Expr:
if isinstance(other, str):
other = Series("", [other])
elif isinstance(other, pl.DataFrame):
return other + self
elif isinstance(other, pl.Expr):
return F.lit(self) + otherView on GitHub (pinned to fe841f959e)