pola-rs/polars · error

cannot set Series of dtype: {self.dtype!r} with list/tuple a

Error message

cannot set Series of dtype: {self.dtype!r} with list/tuple as value; use a scalar value

What it means

Raised by Series.__setitem__ when you assign a list/tuple value to a Series whose dtype is not numeric or temporal. For numeric/temporal dtypes Polars scatters the sequence element-wise, but for String, List, Struct, Categorical, etc. there is no vector path, so it demands a scalar value instead.

Source

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

        [
            10
            99
            99
        ]
        """
        # do the single idx as first branch as those are likely in a tight loop
        if isinstance(key, int) and not isinstance(key, bool):
            self.scatter(key, value)
            return None
        elif isinstance(value, Sequence) and not isinstance(value, str):
            if self.dtype.is_numeric() or self.dtype.is_temporal():
                self.scatter(key, value)  # type: ignore[arg-type]
                return None
            msg = (
                f"cannot set Series of dtype: {self.dtype!r} with list/tuple as value;"
                " use a scalar value"
            )
            raise TypeError(msg)
        if isinstance(key, Series):
            if key.dtype == Boolean:
                self._s = self.set(key, value)._s
            elif key.dtype.is_integer():
                self._s = self.scatter(key, value)._s
            else:
                msg = f"cannot use Series of dtype {key.dtype!r} for indexing; expected boolean or integer dtype"
                raise TypeError(msg)

        # TODO: implement for these types without casting to series
        elif _check_for_numpy(key) and isinstance(key, np.ndarray):
            if key.dtype == np.bool_:
                # boolean numpy mask
                self._s = self.scatter(np.argwhere(key)[:, 0], value)._s
            else:
                s = self._from_pyseries(
                    PySeries.new_u32("", np.array(key, np.uint32), _strict=True)
                )

View on GitHub (pinned to df599052da)

Solutions

  1. Assign a scalar: `s[0] = 'x'`.
  2. For multiple positions on non-numeric dtypes, loop scalars or rebuild the Series: `pl.Series(name, new_values, dtype=s.dtype)`.
  3. For many updates, prefer expression-based replacement: `s.set_at_idx(idx, values)` (check dtype support) or `s.zip_with(mask, other)`.
  4. If the column is genuinely numeric/temporal, check that it was not mis-typed as String during inference.

Example fix

// before
s = pl.Series(['a', 'b', 'c'])
s[[0, 2]] = ['x', 'z']  # TypeError

// after
for i, v in zip([0, 2], ['x', 'z']):
    s[i] = v
# or rebuild:
pl.Series(s.name, ['x', 'b', 'z'])
Defensive patterns

Strategy: validation

Validate before calling

def setitem_value_ok(s: pl.Series, value) -> bool:
    if isinstance(value, (list, tuple)) and not isinstance(value, str):
        return s.dtype.is_numeric() or s.dtype.is_temporal()
    return True

assert setitem_value_ok(s, ['x', 'y']), 'use a scalar for this dtype'

Type guard

def accepts_sequence_value(s: pl.Series) -> bool:
    return s.dtype.is_numeric() or s.dtype.is_temporal()

Try / catch

try:
    s[key] = value
except TypeError as e:
    if 'list/tuple as value' not in str(e):
        raise
    for i, v in zip(indices, value):
        s[i] = v

Prevention

When it happens

Trigger: `s = pl.Series(['a','b','c']); s[[0,1]] = ['x','y']`, `s[0] = ['x']`, `s[mask] = ('p','q')` on a String/Categorical/List/Struct-typed Series. Numeric and temporal Series accept sequences fine (scatter branch just above).

Common situations: Pandas-style multi-cell assignment (`df['col'][[0,1]] = [...]`) ported to Polars; updating string label columns in a loop-free batch; setting a single element but wrapping the value in a list by accident (`s[0] = ['x']` instead of `s[0] = 'x'`).

Related errors


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