pola-rs/polars · error · ValueError

strategy {strategy!r} is not supported

Error message

strategy {strategy!r} is not supported

What it means

Expr.map_elements validates its `strategy` argument and only accepts 'thread_local' (default) or 'threading'. Any other string — including typos like 'threads' or 'parallel', or the value None passed explicitly through a variable — reaches the final else branch and raises ValueError before any data is processed. The 'threading' strategy chunks the Series across the rayon thread pool and is itself marked unstable.

Source

Thrown at py-polars/src/polars/expr/expr.py:5544

                    b = b + step
                    partition_df = df[a:b, :]
                    partitions.append(get_lazy_promise(partition_df))

                from polars.functions.lazy import _collect_all_eager

                out = [df.to_series() for df in _collect_all_eager(partitions)]
                return F.concat(out, rechunk=False)

            return self.map_batches(
                wrap_threading,
                agg_list=False,
                return_dtype=return_dtype,
                returns_scalar=False,
                is_elementwise=True,
            )
        else:
            msg = f"strategy {strategy!r} is not supported"
            raise ValueError(msg)

    @deprecated(
        "`Expr.flatten()` is deprecated and will be removed in version 2.0. "
        "Use `Expr.list.explode(keep_nulls=False, empty_as_null=False)` instead."
    )
    def flatten(self) -> Expr:
        """
        Flatten a list or string column.

        Alias for :func:`Expr.list.explode`.

        .. deprecated:: 1.38
            `Expr.flatten()` is deprecated and will be removed in version 2.0.
            Use `Expr.list.explode(keep_nulls=False, empty_as_null=False)` instead,
            which provides the behavior you likely expect.

        Examples
        --------

View on GitHub (pinned to df599052da)

Solutions

  1. Use strategy='threading' for thread-based parallelism, or omit the argument for 'thread_local'.
  2. If you need process-based parallelism, it is not supported here — implement it outside polars (partition the frame yourself) or use native expressions.
  3. Check for a None default in your config layer and only forward strategy when set.

Example fix

# before
pl.col('a').map_elements(f, strategy='threads')

# after
pl.col('a').map_elements(f, strategy='threading')
Defensive patterns

Strategy: validation

Validate before calling

if strategy is not None:
    assert strategy in ('thread_local', 'threading'), f'bad map_elements strategy: {strategy!r}'

Type guard

def is_map_strategy(s: str) -> bool:
    return s in ('thread_local', 'threading')

Try / catch

try:
    out = expr.map_elements(f, strategy=strat)
except ValueError as e:
    if 'strategy' in str(e):
        out = expr.map_elements(f, strategy='thread_local')
    else:
        raise

Prevention

When it happens

Trigger: pl.col('a').map_elements(f, strategy='multiprocessing'), strategy=None passed via a config variable, or a misspelled value like 'threadin'.

Common situations: Attempting Python-level parallelism with map_elements and guessing a strategy name; config files that default the field to None; copying strategy names from other libraries (pandas 'processes'/'threads').

Related errors


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