pola-rs/polars · error · TypeError

`{func_name!r}` received both `{old_name!r}` and `{new_name!

Error message

`{func_name!r}` received both `{old_name!r}` and `{new_name!r}` as arguments; `{old_name!r}` {is_deprecated}, use `{new_name!r}` instead

What it means

rename_kwarg implements polars' parameter renames: if a caller passes only the deprecated keyword they get a DeprecationWarning and the value is forwarded; if they pass BOTH the old and the new keyword, the intent is ambiguous and polars raises TypeError immediately telling you which name to keep.

Source

Thrown at py-polars/src/polars/_utils/deprecation.py:158

def _rename_keyword_argument(
    old_name: str,
    new_name: str,
    kwargs: dict[str, object],
    func_name: str,
    version: str,
    mapper: Callable[[object], object],
) -> None:
    """Rename a keyword argument of a function."""
    if old_name in kwargs:
        if new_name in kwargs:
            is_deprecated = (
                f"was deprecated in version {version}" if version else "is deprecated"
            )
            msg = (
                f"`{func_name!r}` received both `{old_name!r}` and `{new_name!r}` as arguments;"
                f" `{old_name!r}` {is_deprecated}, use `{new_name!r}` instead"
            )
            raise TypeError(msg)

        in_version = f" in version {version}" if version else ""
        issue_deprecation_warning(
            f"the argument `{old_name}` for `{func_name}` is deprecated. "
            f"It was renamed to `{new_name}`{in_version}."
        )
        kwargs[new_name] = mapper(kwargs.pop(old_name))


def deprecate_nonkeyword_arguments(
    allowed_args: list[str] | None = None, message: str | None = None, *, version: str
) -> IdentityFunction:
    """
    Decorator for deprecating the use of non-keyword arguments in a function.

    Use as follows:

        @deprecate_nonkeyword_arguments(allowed_args=["self", "val"], version="1.0.0")

View on GitHub (pinned to df599052da)

Solutions

  1. Delete the deprecated argument from the call, keeping only the new name.
  2. In wrappers, pop the old key before injecting the new one: kwargs.setdefault(new_name, kwargs.pop(old_name, default)).
  3. Read the deprecation warning issued earlier — it names both the old and new parameter.

Example fix

// before
df.write_csv(path="out.csv", file="out.csv")  # both names -> TypeError

// after
df.write_csv("out.csv")  # new-style positional/new name only
Defensive patterns

Strategy: validation

Validate before calling

def forward_renamed_kwargs(func, kwargs: dict, old_name: str, new_name: str):
    if old_name in kwargs and new_name in kwargs:
        raise TypeError(f"pass only one of {old_name!r}/{new_name!r} to {func.__name__}")
    if old_name in kwargs:
        kwargs[new_name] = kwargs.pop(old_name)
    return func(**kwargs)

Try / catch

try:
    result = fn(**kwargs)
except TypeError as e:
    if "received both" in str(e) and "instead" in str(e):
        import re
        m = re.search(r"received both `(\w+)` and `(\w+)`", str(e))
        if m:
            kwargs.pop(m.group(1), None)  # drop deprecated name, retry
            result = fn(**kwargs)
        else:
            raise
    else:
        raise

Prevention

When it happens

Trigger: Calling a renamed function with both names, e.g. df.write_csv(file=f, path="out.csv") or any wrapper that sets the new kwarg while forwarding **kwargs that still contain the old one.

Common situations: Half-finished migration after a polars major upgrade; utility wrappers doing fn(**kwargs, new_name=default) while callers still send old_name; IDE auto-complete inserting the new name next to the old one.

Related errors


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