pola-rs/polars · error · InvalidOperationError

{how!r} strategy requires at least one common column

Error message

{how!r} strategy requires at least one common column

What it means

The align-family concat strategies join frames on the column names shared by every input. If the intersection of all input schemas is empty there is no key to align on, and Polars raises InvalidOperationError before executing the join. Column-name matching is exact (case- and whitespace-sensitive).

Source

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

        ):
            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
        # a DuplicateError in case of column collision, same as "horizontal")
        join_method: JoinStrategy = (
            "full" if how == "align" else how.removeprefix("align_")  # type: ignore[assignment]
        )
        join_frames = [df.lazy() for df in elems]

        def join_fn(x: pl.LazyFrame, y: pl.LazyFrame) -> pl.LazyFrame:
            return x.join(
                y,
                on=common_cols,
                how=join_method,
                maintain_order="right_left",
                coalesce=True,
            )

        if join_method in ("full", "inner"):

View on GitHub (pinned to df599052da)

Solutions

  1. Inspect schemas per frame and intersect them: set(df1.columns) & set(df2.columns) to find the mismatch
  2. Rename to common keys before concat: df2.rename({'c': 'a'})
  3. Normalize headers first (strip/lower) when sources are inconsistent
  4. If no shared key was intended, use how='horizontal' instead of an align strategy

Example fix

# before
pl.concat([df1, df2], how='align')  # no common columns

# after
df2 = df2.rename({'c': 'a'})
pl.concat([df1, df2], how='align')

# or, if no key was intended:
pl.concat([df1, df2], how='horizontal')
Defensive patterns

Strategy: validation

Validate before calling

schemas = [set(f.collect_schema().names()) if hasattr(f, 'collect_schema') else set(f.columns) for f in frames]
common = set.intersection(*schemas) if schemas else set()
if how.startswith('align') and not common:
    raise ValueError(f'no common columns to align on: {[sorted(s) for s in schemas]}')
out = pl.concat(frames, how=how)

Try / catch

import polars as pl

try:
    out = pl.concat(frames, how='align')
except pl.exceptions.InvalidOperationError as e:
    if 'common column' not in str(e):
        raise
    out = pl.concat(frames, how='horizontal')  # deliberate fallback

Prevention

When it happens

Trigger: pl.concat([df1, df2], how='align') where df1 has columns ['a','b'] and df2 has ['c','d']; case-mismatched names ('Id' vs 'id'); trailing whitespace in headers from CSVs; a rename applied to one frame upstream.

Common situations: Merging monthly extracts whose schemas drifted over time; case/whitespace differences from different data sources; accidental renames before the align call; assuming align does outer-horizontal concat instead of key-based alignment.

Related errors


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