pola-rs/polars · error · TypeError

{how!r} strategy is not supported for {qualified_type_name(e

Error message

{how!r} strategy is not supported for {qualified_type_name(elems[0])!r}

What it means

The align / align_left / align_right / align_inner / align_full concat strategies align frames by joining on their common columns, which is only defined for all-DataFrame or all-LazyFrame input sequences. If the sequence contains Series, Expr, or mixed frame types, this TypeError names the first element's qualified type before any alignment runs.

Source

Thrown at py-polars/src/polars/functions/eager.py:234

    elems: Sequence[PolarsType] = list(items)

    if not elems:
        msg = "cannot concat empty list"
        raise ValueError(msg)

    if len(elems) == 1 and isinstance(
        elems[0], (pl.DataFrame, pl.Series, pl.LazyFrame)
    ):
        return elems[0]

    if how.startswith("align"):
        if not is_non_empty_sequence_of(
            elems, pl.DataFrame
        ) and not is_non_empty_sequence_of(  # type: ignore[redundant-expr]
            elems, pl.LazyFrame
        ):
            msg = f"{how!r} strategy is not supported for {qualified_type_name(elems[0])!r}"
            raise TypeError(msg)

        # establish common columns, maintaining the order in which they appear
        all_columns = list(chain.from_iterable(e.collect_schema() for e in elems))
        key = {v: k for k, v in enumerate(ordered_unique(all_columns))}
        output_column_order = list(key)
        common_cols = sorted(
            reduce(
                lambda x, y: set(x) & set(y),  # type: ignore[arg-type, return-value]
                chain(e.collect_schema() for e in elems),
            ),
            key=lambda k: key.get(k, 0),
        )
        # we require at least one key column for 'align' strategies
        if not common_cols:
            msg = f"{how!r} strategy requires at least one common column"
            raise InvalidOperationError(msg)

        # align frame data using a join, with no suffix-resolution (will raise

View on GitHub (pinned to df599052da)

Solutions

  1. For Series inputs use how='vertical' (the only Series strategy)
  2. Convert Series to named single-column frames first: s.to_frame(), then use align
  3. Make all inputs the same kind: call .lazy() on every DataFrame (or collect every LazyFrame) before concat with an align strategy

Example fix

# before
pl.concat([s1, s2], how='align')

# after
pl.concat([s1.to_frame(), s2.to_frame()], how='align')
# or, if vertical stacking was intended:
pl.concat([s1, s2], how='vertical')
Defensive patterns

Strategy: validation

Validate before calling

if how.startswith('align'):
    if not all(isinstance(f, (pl.DataFrame, pl.LazyFrame)) for f in frames):
        frames = [
            f.to_frame() if isinstance(f, pl.Series) else f for f in frames
        ]
    assert all(type(f) is type(frames[0]) for f in frames), 'mixed frame types'
out = pl.concat(frames, how=how)

Type guard

def all_frames_of_kind(xs: object) -> bool:
    return bool(xs) and all(
        isinstance(x, (pl.DataFrame, pl.LazyFrame)) and type(x) is type(xs[0])
        for x in xs
    )

Prevention

When it happens

Trigger: pl.concat([s1, s2], how='align') with Series inputs; mixing a DataFrame with a LazyFrame under an align strategy; passing a list of Expr with how='align_full'.

Common situations: Assuming align behaves like pandas concat(axis=1) for arbitrary objects; heterogeneous pipelines where one stage returns a Series instead of a DataFrame; forgetting .lazy()/to_frame() conversions before aligning.

Related errors


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