pola-rs/polars · error · TypeError
'suffix' must be a string; found {qualified_type_name(suffix
Error message
'suffix' must be a string; found {qualified_type_name(suffix)!r} What it means
Expr.cat.ends_with is the suffix counterpart of starts_with: the suffix must be a Python str, and any other type raises TypeError with the found type's qualified name. Comparison happens on string representations of categorical values, so a concrete string suffix is required.
Source
Thrown at py-polars/src/polars/expr/categorical.py:259
│ mango ┆ true │
│ null ┆ null │
└────────┴────────────┘
Using `ends_with` as a filter condition:
>>> df.filter(pl.col("fruits").cat.ends_with("go"))
shape: (1, 1)
┌────────┐
│ fruits │
│ --- │
│ cat │
╞════════╡
│ mango │
└────────┘
"""
if not isinstance(suffix, str):
msg = f"'suffix' must be a string; found {qualified_type_name(suffix)!r}"
raise TypeError(msg)
return wrap_expr(self._pyexpr.cat_ends_with(suffix))
def slice(self, offset: int, length: int | None = None) -> Expr:
"""
Extract a substring from the string representation of each value.
.. engine-support:: in-memory, streaming, distributed
Parameters
----------
offset
Start index. Negative indexing is supported.
length
Length of the slice. If set to `None` (default), the slice is taken to the
end of the string.
Returns
-------View on GitHub (pinned to df599052da)
Solutions
- Decode bytes to str first: suffix.decode() if isinstance(suffix, bytes) else suffix
- Coerce at the boundary: .cat.ends_with(str(suffix))
- For per-row dynamic suffixes, cast to String and use .str.ends_with(other_expr)
Example fix
# before
pl.col('cat_col').cat.ends_with(b'go') # TypeError
# after
pl.col('cat_col').cat.ends_with(b'go'.decode())
# per-row dynamic: pl.col('cat_col').cast(pl.String).str.ends_with(pl.col('suffix_col')) Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(suffix, bytes):
suffix = suffix.decode()
assert isinstance(suffix, str), 'cat.ends_with requires a str suffix'
expr = pl.col('c').cat.ends_with(suffix) Type guard
from typing import TypeGuard
def is_str_suffix(s) -> TypeGuard[str]:
return isinstance(s, str) Try / catch
try:
e = pl.col('c').cat.ends_with(suffix)
except TypeError:
e = pl.col('c').cast(pl.String).str.ends_with(str(suffix)) Prevention
- Decode bytes suffixes at ingestion boundaries
- For per-row dynamic suffixes use cast(pl.String).str.ends_with(other_expr)
When it happens
Trigger: pl.col('c').cat.ends_with(b'go') (bytes), .cat.ends_with(42), or .cat.ends_with(pl.lit('go')).
Common situations: Suffixes arriving as bytes from binary pipelines; passing expressions out of habit; programmatic suffix values from untyped config dicts.
Related errors
- 'prefix' must be a string; found {qualified_type_name(prefix
- unexpected column selection {col_selection!r}
- cannot use `__setitem__` on DataFrame with key {key!r} of ty
- expected 'time' to be a Python time or Polars expression, fo
- 'offset' must be an integer, string, or expression, not {typ
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/a53d9de345e13b4f.
Report an issue: GitHub.