pola-rs/polars · error · TypeError
`replace_with` argument is required if `patterns` argument i
Error message
`replace_with` argument is required if `patterns` argument is not a Mapping type
What it means
Expr.str.replace_many accepts patterns without replace_with only when patterns is a Mapping (dict of pattern to replacement); keys and values are then split internally. With a list, Series, or Expr of patterns the replacements are unknown, so omitting replace_with raises a TypeError immediately.
Source
Thrown at py-polars/src/polars/expr/string.py:2911
>>> df = pl.DataFrame({"haystack": ["abcd"]})
>>> patterns = {"abcd": "z", "abc": "y", "b": "x"}
>>> df.with_columns(
... replaced=pl.col("haystack").str.replace_many(patterns, leftmost=True)
... )
shape: (1, 2)
┌──────────┬──────────┐
│ haystack ┆ replaced │
│ --- ┆ --- │
│ str ┆ str │
╞══════════╪══════════╡
│ abcd ┆ z │
└──────────┴──────────┘
""" # noqa: W505
if replace_with is NO_DEFAULT:
if not isinstance(patterns, Mapping):
msg = "`replace_with` argument is required if `patterns` argument is not a Mapping type"
raise TypeError(msg)
# Early return in case of an empty mapping.
if not patterns:
return wrap_expr(self._pyexpr)
replace_with = list(patterns.values())
patterns = list(patterns.keys())
patterns_pyexpr = parse_into_expression(
patterns, # type: ignore[arg-type]
str_as_lit=False,
)
replace_with_pyexpr = parse_into_expression(replace_with, str_as_lit=True)
return wrap_expr(
self._pyexpr.str_replace_many(
patterns_pyexpr, replace_with_pyexpr, ascii_case_insensitive, leftmost
)
)
@unstable()View on GitHub (pinned to df599052da)
Solutions
- Pass a dict: .str.replace_many({'foo': 'bar', 'a': 'b'})
- Or keep the list and provide replace_with: .str.replace_many(pats, replace_with=repls) — a scalar or list-like of replacements
- If patterns/replacements come from a frame, pass expressions: .str.replace_many(pl.col('pats'), replace_with=pl.col('repls'))
Example fix
# before
pl.col('s').str.replace_many(['foo', 'bar'])
# after (mapping)
pl.col('s').str.replace_many({'foo': 'bar', 'bar': 'baz'})
# after (parallel lists)
pl.col('s').str.replace_many(pats, replace_with=repls) Defensive patterns
Strategy: validation
Validate before calling
from collections.abc import Mapping
if not isinstance(patterns, Mapping) and replace_with is None:
raise ValueError('replace_with is required for non-mapping patterns')
expr = pl.col('s').str.replace_many(patterns, replace_with=replace_with) Type guard
from collections.abc import Mapping
def is_pattern_mapping(x: object) -> bool:
return isinstance(x, Mapping) Prevention
- Prefer the dict form (patterns -> replacements) as the default
- When loading replacement tables from files, build a dict immediately
- Wrap the API in one helper that always supplies replace_with for lists
When it happens
Trigger: .str.replace_many(['foo', 'bar']) with no second argument; passing a Series of patterns positionally; refactoring a dict into two parallel lists and forgetting to add replace_with; wrapper functions that forward patterns but drop the default replace_with.
Common situations: Token replacement tables loaded from CSV/DB as two parallel columns; building patterns dynamically at runtime; migrating from chained .str.replace calls where the replacement was always given.
Related errors
- "pad_start" expects a `str`, given a {qualified_type_name(fi
- "pad_end" expects a `str`, given a {qualified_type_name(fill
- "extract_groups" expects a `str`, given a {qualified_type_na
- cannot select columns using key of type {qualified_type_name
- cannot select rows using key of type {qualified_type_name(ke
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/5f5b0332663e9da6.
Report an issue: GitHub.