pola-rs/polars · error
the truth value of a Series is ambiguous Here are some thin
Error message
the truth value of a Series is ambiguous Here are some things you might want to try: - instead of `if s`, use `if not s.is_empty()` - instead of `s1 and s2`, use `s1 & s2` - instead of `s1 or s2`, use `s1 | s2` - instead of `s in [y, z]`, use `s.is_in([y, z])`
What it means
Series.__bool__ (py-polars/src/polars/series/series.py:752) deliberately raises TypeError because a Series has no single truth value: it is a collection of many elements, so `if s:` is ambiguous (length? all-true? any-true?). Python calls __bool__ for bool(s), `if s`, and the and/or operators, and polars rejects all of them with an actionable hint message.
Source
Thrown at py-polars/src/polars/series/series.py:752
Examples
--------
>>> s = pl.Series("a", [1, 2, 3])
>>> s.shape
(3,)
"""
return (self._s.len(),)
def __bool__(self) -> NoReturn:
msg = (
"the truth value of a Series is ambiguous"
"\n\n"
"Here are some things you might want to try:\n"
"- instead of `if s`, use `if not s.is_empty()`\n"
"- instead of `s1 and s2`, use `s1 & s2`\n"
"- instead of `s1 or s2`, use `s1 | s2`\n"
"- instead of `s in [y, z]`, use `s.is_in([y, z])`\n"
)
raise TypeError(msg)
def __getstate__(self) -> bytes:
return self._s.__getstate__()
def __setstate__(self, state: bytes) -> None:
self._s = Series()._s # Initialize with a dummy
self._s.__setstate__(state)
def __str__(self) -> str_:
s_repr: str = self._s.as_str()
return s_repr.replace("Series", f"{self.__class__.__name__}", 1)
def __repr__(self) -> str_:
return self.__str__()
def __len__(self) -> int:
return self.len()
View on GitHub (pinned to df599052da)
Solutions
- Emptiness: if s.is_empty(): ... (or `if not s.is_empty()`)
- Elementwise logic: use s1 & s2 (and), s1 | s2 (or), ~s (not); for reduction use s.all() / s.any()
- Membership: s.is_in([y, z]) instead of `s in [y, z]`
- For tests use assert_series_equal instead of assert
Example fix
# before if s1 and s2: ... if s in ["a", "b"]: ... # after if not (s1 & s2).is_empty(): ... mask = s1 & s2 # elementwise 'and' if s.is_in(["a", "b"]).any(): ...
Defensive patterns
Strategy: validation
Validate before calling
# Decide intent explicitly before branching on a Series:
if s.is_empty(): # instead of: if not s
...
mask = (s1 > 0) & (s2 > 0) # instead of: (s1 > 0) and (s2 > 0)
if mask.any(): # reduction instead of truth of Series
... Type guard
from polars import Series
def as_bool(x: object) -> bool:
"""Only allow real bools; fail loudly for Series."""
if isinstance(x, Series):
raise TypeError("cannot coerce Series to bool; use .any()/.all()/.is_empty()")
return bool(x) Try / catch
try:
flag = bool(result) # result is sometimes a Series
except TypeError as e:
if "truth value of a Series is ambiguous" in str(e):
flag = result.any() if hasattr(result, "any") else False
else:
raise Prevention
- Never use `if series:` — pick is_empty(), .any(), or .all() per intent
- Use & | ~ for elementwise boolean logic; is_in() for membership
- In tests use polars.testing.assert_series_equal, never assert series
When it happens
Trigger: if s: ...; bool(s); s1 and s2; s1 or s2; `s in [a, b]` (uses __eq__ then truth evaluation of the result); passing a Series to assert; using a Series where a plain bool is required (e.g. ternary condition).
Common situations: Code written for a single scalar value later reused with a Series; wrapping results in assert; `if result:` guards after operations that sometimes return Series. The fix depends on intent: emptiness, all/any, or set membership.
Related errors
- Series name must be a string
- cannot treat Series of type {s.dtype} as indices
- {how!r} strategy is not supported for {qualified_type_name(e
- Unrecognised connection type {qualified_type_name(conn)!r};
- invalid input for `exclude`\n\nExpected one or more `str` or
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/adbfd5d61dbb8187.
Report an issue: GitHub.