pola-rs/polars · error · TypeError
cannot exclude by both column name and dtype
Error message
cannot exclude by both column name and dtype
What it means
Thrown by Selector.exclude (py-polars/src/polars/selectors.py:590) when a single exclude() call receives BOTH column-name strings AND dtypes, e.g. exclude("a", pl.Int64). The implementation must build either a by-name or a by-dtype exclusion selector, so mixing the two kinds in one call is ambiguous and rejected with TypeError. Note this fires only when at least one of each kind is present in the same call.
Source
Thrown at py-polars/src/polars/selectors.py:590
if isinstance(columns, Collection) and not isinstance(columns, str)
else [columns]
),
*more_columns,
):
if isinstance(item, str):
exclude_cols.append(item)
elif is_polars_dtype(item):
exclude_dtypes.append(item)
else:
msg = (
"invalid input for `exclude`"
f"\n\nExpected one or more `str` or `DataType`; found {item!r} instead."
)
raise TypeError(msg)
if exclude_cols and exclude_dtypes:
msg = "cannot exclude by both column name and dtype"
raise TypeError(msg)
excluded = (
by_dtype(exclude_dtypes)
if exclude_dtypes
else Selector._by_name(
exclude_cols,
strict=False,
expand_patterns=True,
)
)
return self - excluded
def as_expr(self) -> Expr:
"""
Materialize the `selector` as a normal expression.
This ensures that the operators `|`, `&`, `~` and `-`
are applied on the data and not on the selector sets.View on GitHub (pinned to df599052da)
Solutions
- Chain two exclude calls: cs.all().exclude("foo").exclude(pl.Utf8)
- Or compose a single complement selector: cs.all() - (cs.by_name("foo") | cs.by_dtype(pl.Utf8))
- If args are dynamic, partition them first: names = [a for a in args if isinstance(a, str)]; dtypes = [a for a in args if not isinstance(a, str)], then apply each group separately
Example fix
# before
sel = cs.all().exclude("foo", pl.Utf8)
# after
sel = cs.all().exclude("foo").exclude(pl.Utf8)
# or
sel = cs.all() - (cs.by_name("foo") | cs.by_dtype(pl.Utf8)) Defensive patterns
Strategy: validation
Validate before calling
names = [a for a in args if isinstance(a, str)] dtypes = [a for a in args if not isinstance(a, str)] assert not (names and dtypes), "exclude: split names and dtypes into separate calls" sel = base.exclude(*names).exclude(*dtypes)
Try / catch
try:
sel = base.exclude(*args)
except TypeError as e:
if "cannot exclude by both" in str(e):
names = [a for a in args if isinstance(a, str)]
dtypes = [a for a in args if not isinstance(a, str)]
sel = base.exclude(*names).exclude(*dtypes)
else:
raise Prevention
- Keep name-based and dtype-based exclusions in separate .exclude() calls by convention
- In shared helpers, partition args into names/dtypes before calling exclude
When it happens
Trigger: cs.all().exclude("foo", pl.Utf8), cs.numeric().exclude(["bar", pl.Float64]), or cs.all().exclude(*names, *dtypes) where names is a list of strings and dtypes a list of DataType instances.
Common situations: Dynamically building an exclusion list from two sources (user-supplied column names plus a fixed dtype list) and splatting them into one exclude() call. Refactors that merge two exclude calls into one also trip this.
Related errors
- invalid input for `exclude`\n\nExpected one or more `str` or
- invalid dtype: {t!r}
- invalid dtype: {tp!r}
- invalid index value: {idx!r}
- invalid name: {n!r}
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/2d4cd8a5c3df5f80.
Report an issue: GitHub.