pola-rs/polars · error · ValueError

cross join should not pass join keys

Error message

cross join should not pass join keys

What it means

A cross join (how='cross') is the Cartesian product of both frames and takes no join keys. Passing on=, left_on=, or right_on= together with how='cross' raises ValueError immediately.

Source

Thrown at py-polars/src/polars/lazyframe/frame.py:6447

            raise ValueError(msg)

        if how == "outer":
            how = "full"
            issue_deprecation_warning(
                "use of `how='outer'` should be replaced with `how='full'`.",
                version="0.20.29",
            )
        elif how == "outer_coalesce":  # type: ignore[comparison-overlap]
            coalesce = True
            how = "full"
            issue_deprecation_warning(
                "use of `how='outer_coalesce'` should be replaced with `how='full', coalesce=True`.",
                version="0.20.29",
            )
        elif how == "cross":
            if uses_on or uses_lr_on:
                msg = "cross join should not pass join keys"
                raise ValueError(msg)
            return self._from_pyldf(
                self._ldf.join(
                    other._ldf,
                    [],
                    [],
                    allow_parallel,
                    force_parallel,
                    nulls_equal,
                    how,
                    suffix,
                    validate,
                    maintain_order,
                    build_side=build_side,
                    coalesce=None,
                )
            )

        if uses_on:

View on GitHub (pinned to df599052da)

Solutions

  1. Remove all key arguments for cross joins: lf.join(other, how='cross')
  2. In generic wrappers, conditionally omit keys when how == 'cross'
  3. Consider pl.concat(..., how='diagonal') or product logic if a keyed cross-like result was intended

Example fix

# before
lf.join(other, on='id', how='cross')

# after
lf.join(other, how='cross')
Defensive patterns

Strategy: validation

Validate before calling

if how == 'cross':
    lf = lf.join(other, how='cross')
else:
    lf = lf.join(other, on=on, left_on=left_on, right_on=right_on, how=how)

Type guard

def is_keyless_join(how: str) -> bool:
    return how == 'cross'

Prevention

When it happens

Trigger: lf.join(other, on='id', how='cross'); generic join wrappers that always forward join keys even when the caller selects cross; changing how= to 'cross' in existing code without removing keys.

Common situations: Switching an existing join to cross for combinatorics (e.g. grid generation); shared join helper functions with fixed key parameters.

Related errors


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