pola-rs/polars · error · TypeError

'length' must be an integer, string, or expression, not

Error message

'length' must be an integer, string, or expression, not {type(length).__name__}

What it means

Expr.list.slice() validates its `length` argument: when supplied it must be an integer, string column name, or Expr. Passing a Collection (list/tuple/dict/set) raises this TypeError. Polars checks the types client-side so invalid expressions fail fast.

Solutions

  1. Unwrap the collection and pass the integer directly: list.slice(0, 3).
  2. If the value is in a list like [n], use n (i.e. values[0]).
  3. If length should be dynamic, pass a column name (str) or an Expr such as pl.col('n').

Example fix

// before
pl.col('items').list.slice(0, [3])
// after
pl.col('items').list.slice(0, 3)
Defensive patterns

Strategy: type-guard

Validate before calling

if length is not None and not isinstance(length, (int, str, pl.Expr)):
    raise TypeError(f'length must be int/str/Expr, got {type(length).__name__}')

Type guard

def is_valid_length(v) -> bool:
    return v is None or isinstance(v, (int, str, pl.Expr))

Try / catch

try:
    expr = pl.col('a').list.slice(offset, length)
except TypeError:
    expr = pl.col('a').list.slice(offset, int(length[0]))

Prevention

When it happens

Trigger: Calling Expr.list.slice(offset, length) with length as a collection, e.g. list.slice(0, [3]) or list.slice(1, (2,)).

Common situations: Passing a one-element list holding the intended length; confusing slice length with an end index; wrapping the length in a list during programmatic argument construction.

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


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/b8394ffd9d69e073. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/expr/list.py:1134

        ┌─────────────┬───────────┐
        │ a           ┆ slice     │
        │ ---         ┆ ---       │
        │ list[i64]   ┆ list[i64] │
        ╞═════════════╪═══════════╡
        │ [1, 2, … 4] ┆ [2, 3]    │
        │ [10, 2, 1]  ┆ [2, 1]    │
        └─────────────┴───────────┘
        """
        if isinstance(offset, Collection) and not isinstance(offset, str):
            msg = f"'offset' must be an integer, string, or expression, not {type(offset).__name__}"
            raise TypeError(msg)
        if (
            length is not None
            and isinstance(length, Collection)
            and not isinstance(length, str)
        ):
            msg = f"'length' must be an integer, string, or expression, not {type(length).__name__}"
            raise TypeError(msg)

        offset_pyexpr = parse_into_expression(offset)
        length_pyexpr = parse_into_expression(length)
        return wrap_expr(self._pyexpr.list_slice(offset_pyexpr, length_pyexpr))

    def head(self, n: int | str | Expr = 5) -> Expr:
        """
        Slice the first `n` values of every sub-list.

        .. engine-support:: in-memory, streaming, distributed

        Parameters
        ----------
        n
            Number of values to return for each sublist.

        Examples
        --------

View on GitHub (pinned to fe841f959e)