pola-rs/polars · error · ValueError

cannot concat empty list

Error message

cannot concat empty list

What it means

pl.concat requires at least one DataFrame, Series, LazyFrame, or Expr; an empty list — or a generator that yields nothing — raises ValueError immediately after the input is materialized. Polars will not invent an output schema for an empty concat, so there is no defined empty result to return.

Source

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

    ╞═════╪══════╪══════╪═════╡
    │ 1   ┆ null ┆ null ┆ 7   │
    │ 3   ┆ null ┆ 6    ┆ 8   │
    └─────┴──────┴──────┴─────┘
    >>> pl.concat([df_a1, df_a2, df_a3], how="align_inner")
    shape: (0, 4)
    ┌─────┬─────┬─────┬─────┐
    │ id  ┆ x   ┆ y   ┆ z   │
    │ --- ┆ --- ┆ --- ┆ --- │
    │ i64 ┆ i64 ┆ i64 ┆ i64 │
    ╞═════╪═════╪═════╪═════╡
    └─────┴─────┴─────┴─────┘
    """  # noqa: W505
    # unpack/standardise (handles generator input)
    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))}

View on GitHub (pinned to df599052da)

Solutions

  1. Guard before calling: if not frames, return an explicitly-typed empty result (pl.DataFrame(schema=expected_schema))
  2. Treat the empty case as a signal and check upstream why nothing was produced
  3. For partitioned pipelines, skip the concat step for empty partitions

Example fix

# before
pl.concat(frames)

# after
if not frames:
    out = pl.DataFrame(schema=expected_schema)
else:
    out = pl.concat(frames)
Defensive patterns

Strategy: validation

Validate before calling

frames = list(frames)
if not frames:
    out = pl.DataFrame(schema=expected_schema)  # explicit empty result
else:
    out = pl.concat(frames)

Try / catch

try:
    out = pl.concat(frames)
except ValueError as e:
    if 'empty' in str(e):
        out = pl.DataFrame(schema=expected_schema)
    else:
        raise

Prevention

When it happens

Trigger: pl.concat([]); pl.concat(df for df in frames if keep(df)) where the filter removes everything; concat of partitions from a group_by/split that happens to be empty; a loop that appends frames but never runs its body.

Common situations: Batch/ETL jobs where all input files were filtered out or missing; empty partitions in parallel processing; optional input lists that resolved to zero items; error-swallowing upstream code that silently produced no frames.

Related errors


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