pola-rs/polars · error · ValueError

'left_on' requires corresponding 'right_on'

Error message

'left_on' requires corresponding 'right_on'

What it means

LazyFrame.join() requires `left_on` and `right_on` to be provided together: they pair each left key column with a corresponding right key column. Supplying only one leaves the pairing incomplete, so a ValueError is raised.

Solutions

  1. Provide both: lf.join(other, left_on='lkey', right_on='rkey')
  2. If the key column name is identical in both frames, use `on='key'` instead
  3. For multiple keys, pass equal-length lists to left_on and right_on

Example fix

// before
df.join(other, left_on='user_id')
// after
df.join(other, left_on='user_id', right_on='uid')
Defensive patterns

Strategy: validation

Validate before calling

def check_lr_pair(left_on, right_on):
    if (left_on is None) != (right_on is None):
        raise ValueError('left_on and right_on must be provided together')

Type guard

def lr_pair_complete(left_on, right_on) -> bool:
    return (left_on is None) == (right_on is None)

Try / catch

try:
    out = df.join(other, left_on=lk, right_on=rk)
except ValueError as e:
    if "'left_on' requires corresponding 'right_on'" in str(e):
        raise KeyError(f'missing join key: left_on={lk!r} needs right_on=') from e
    raise

Prevention

When it happens

Trigger: Calling lf.join(other, left_on='lkey') without right_on, or lf.join(other, right_on='rkey') without left_on; also passing a list to one side and None to the other.

Common situations: Joining frames whose key columns have different names and forgetting the second parameter; partial edits when renaming join keys; misunderstanding that `on` cannot substitute for one of the pair.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/e1c7935426fe3e9c. Report an issue: GitHub.

Appendix: source

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

        │ 3   ┆ 8.0 ┆ c   ┆ y     ┆ b         │
        │ 3   ┆ 8.0 ┆ c   ┆ z     ┆ d         │
        └─────┴─────┴─────┴───────┴───────────┘
        """
        require_same_type(self, other)

        if maintain_order is None:
            maintain_order = "none"

        uses_on = on is not None
        uses_left_on = left_on is not None
        uses_right_on = right_on is not None
        uses_lr_on = uses_left_on or uses_right_on
        if uses_on and uses_lr_on:
            msg = "cannot use 'on' in conjunction with 'left_on' or 'right_on'"
            raise ValueError(msg)
        elif uses_left_on != uses_right_on:
            msg = "'left_on' requires corresponding 'right_on'"
            raise ValueError(msg)

        if how == "outer":  # type: ignore[comparison-overlap]
            msg = "use of `how='outer'` should be replaced with `how='full'`."
            raise ValueError(msg)
        elif how == "outer_coalesce":  # type: ignore[comparison-overlap]
            msg = "use of `how='outer_coalesce'` should be replaced with `how='full', coalesce=True`."
            raise ValueError(msg)
        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,

View on GitHub (pinned to fe841f959e)