pola-rs/polars · error · TypeError
'suffix' must be a string; found
Error message
'suffix' must be a string; found {qualified_type_name(suffix)!r} What it means
Type-guard on the `suffix` parameter of the categorical ends_with method. The Python layer validates the argument before handing it to the Rust cat_ends_with implementation; passing anything other than a str (e.g. None, bytes, or a column-like object) triggers this TypeError naming the actual type received.
Solutions
- Wrap the value with str(...) before calling
- Decode bytes to str if the suffix comes from binary input
- Guard with isinstance(suffix, str) and raise a clear error of your own
- Confirm the variable passed actually holds the suffix string
Example fix
// before cat_col.cat.ends_with(version) # version = 2 (int) // after cat_col.cat.ends_with(str(version))
Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(suffix, str):
raise TypeError(f'suffix must be str, got {type(suffix).__name__}') Type guard
def is_str(x) -> bool:
return isinstance(x, str) Try / catch
try:
e = col.cat.ends_with(suffix)
except TypeError as e:
if 'must be a string' in str(e):
e = col.cat.ends_with(suffix.decode() if isinstance(suffix, bytes) else str(suffix))
else:
raise Prevention
- Coerce enum/numeric suffix values with str() before use
- Validate config-derived suffixes are strings at load time
- Avoid passing bytes; decode first
When it happens
Trigger: Calling pl.col('c').cat.ends_with(42), ends_with(b'ngo'), ends_with(None), or passing an int/enum value instead of the string suffix.
Common situations: Suffix stored as a number in config (e.g. version suffix 1 instead of '1'); bytes from decoded data; variable mix-ups in generated expressions.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- 'prefix' must be a string; found
- arr.to_struct() got a str instead of a list. hint: pass
- cannot call `map_groups` when filtering groups with `having`
- cannot call `map_groups` when grouping by an expression
- cannot call `map_groups` when grouping by named expressions
AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18).
Data as JSON: /api/errors/a53d9de345e13b4f.
Report an issue: GitHub.
Appendix: source
Thrown at py-polars/src/polars/expr/categorical.py:231
│ 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 fe841f959e)