pola-rs/polars · error

Series name must be a string

Error message

Series name must be a string

What it means

Raised by the Series constructor (py-polars/src/polars/series/series.py:293) when name is given, is not a string, AND values are also given. The constructor has one convenience overload — pl.Series([1,2,3]) puts the data in the name slot — but that only works when values is None; once both positional args are supplied, a non-str name is unambiguous misuse and raises TypeError.

Source

Thrown at py-polars/src/polars/series/series.py:293

        # If 'Unknown' treat as None to trigger type inference
        if dtype == Unknown:
            dtype = None
        elif dtype is not None and not is_polars_dtype(dtype):
            dtype = parse_into_dtype(dtype)

        # Handle case where values are passed as the first argument
        original_name: str | None = None
        if name is None:
            name = ""
        elif isinstance(name, str):
            original_name = name
        else:
            if values is None:
                values = name
                name = ""
            else:
                msg = "Series name must be a string"
                raise TypeError(msg)

        if isinstance(values, Sequence):
            self._s = sequence_to_pyseries(
                name,
                values,
                dtype=dtype,
                strict=strict,
                nan_to_null=nan_to_null,
            )

        elif values is None:
            self._s = sequence_to_pyseries(name, [], dtype=dtype)

        elif _check_for_numpy(values) and isinstance(values, np.ndarray):
            self._s = numpy_to_pyseries(
                name, values, strict=strict, nan_to_null=nan_to_null
            )
            if values.dtype.type in [np.datetime64, np.timedelta64]:

View on GitHub (pinned to df599052da)

Solutions

  1. Give the name as a string: pl.Series("prices", [1, 2, 3])
  2. If the first arg was meant to be data only, drop the second: pl.Series([1, 2, 3])
  3. If name comes from a variable, coerce: pl.Series(str(name) if name is not None else None, values)

Example fix

# before
s = pl.Series(0, [10, 20, 30])  # int name + values

# after
s = pl.Series("prices", [10, 20, 30])
# data-only form:
s = pl.Series([10, 20, 30])
Defensive patterns

Strategy: type-guard

Validate before calling

def make_series(name, values):
    if name is not None and not isinstance(name, str):
        raise TypeError(f"Series name must be str, got {type(name).__name__}")
    return pl.Series(name, values)

Type guard

from typing import TypeGuard

def is_series_name(x: object) -> TypeGuard[str]:
    return x is None or isinstance(x, str)

Try / catch

try:
    s = pl.Series(name, values)
except TypeError as e:
    if "name must be a string" in str(e):
        s = pl.Series(str(name), values)
    else:
        raise

Prevention

When it happens

Trigger: pl.Series(0, [1, 2, 3]) (index-like name), pl.Series(("a",), [1, 2]), pl.Series(1.0, [1.0]), or splatting a variable that is sometimes a list: pl.Series(maybe_data, other_data).

Common situations: Pandas habits (pd.Series(data, index=...)) where a number is passed as the first arg; code that passes a name variable which is None only sometimes — note pl.Series(None, [1,2]) is fine because None is special-cased; passing a tuple/dict as name.

Related errors


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