{"record":{"id":"a347c532bc8cb906","repo":"pola-rs/polars","slug":"must-specify-on-or-left-on-and-right-on","errorCode":null,"errorMessage":"must specify `on` OR `left_on` and `right_on`","messagePattern":"must specify `on` OR `left_on` and `right_on`","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/lazyframe/frame.py","lineNumber":6267,"sourceCode":"                    how,\n                    suffix,\n                    validate,\n                    maintain_order,\n                    build_side=build_side,\n                    coalesce=None,\n                )\n            )\n\n        if uses_on:\n            pyexprs = parse_into_list_of_expressions(on)\n            pyexprs_left = pyexprs\n            pyexprs_right = pyexprs\n        elif uses_lr_on:\n            pyexprs_left = parse_into_list_of_expressions(left_on)\n            pyexprs_right = parse_into_list_of_expressions(right_on)\n        else:\n            msg = \"must specify `on` OR `left_on` and `right_on`\"\n            raise ValueError(msg)\n\n        return self._from_pyldf(\n            self._ldf.join(\n                other._ldf,\n                pyexprs_left,\n                pyexprs_right,\n                allow_parallel,\n                force_parallel,\n                nulls_equal,\n                how,\n                suffix,\n                validate,\n                maintain_order,\n                build_side,\n                coalesce,\n            )\n        )\n","sourceCodeStart":6249,"sourceCodeEnd":6285,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/py-polars/src/polars/lazyframe/frame.py#L6249-L6285","documentation":"LazyFrame.join() needs join keys: either `on` alone, or `left_on` together with `right_on`. If none of these is provided (and the strategy isn't 'cross'), there is no way to match rows, so a ValueError is raised.","triggerScenarios":"Calling lf.join(other) or lf.join(other, how='inner') with no key arguments; also passing only `by`-style auxiliary parameters meant for join_asof.","commonSituations":"Porting pandas code that merges on indexes; forgetting keys after refactoring; copying a cross-join call (which omits keys legally) and then adding a non-cross `how`.","solutions":["Add on='key' when the key column name matches in both frames","Or add left_on='lkey', right_on='rkey' for differently named keys","For multiple keys pass lists: on=['a','b'] or left_on=[...], right_on=[...]"],"exampleFix":"// before\ndf.join(other, how='left')\n// after\ndf.join(other, on='id', how='left')","handlingStrategy":"validation","validationCode":"def require_keys(on, left_on, right_on, how):\n    if how != 'cross' and on is None and left_on is None and right_on is None:\n        raise ValueError('join requires on= or left_on/right_on=')","typeGuard":"def has_join_keys(on, left_on, right_on) -> bool:\n    return on is not None or (left_on is not None and right_on is not None)","tryCatchPattern":"try:\n    out = df.join(other, on=key, how=how)\nexcept ValueError as e:\n    if 'must specify `on` OR' in str(e):\n        raise KeyError('join() needs on= or left_on/right_on= arguments') from e\n    raise","preventionTips":["Always pass on= explicitly; never rely on defaults for join keys","Don't confuse join_asof's `by` with join keys","For index-style joins, materialize the index as a column and join on it"],"tags":["polars","python","join","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e","analyzedAt":"2026-09-18T22:14:11.667Z","contentChangedAt":"2026-09-18T22:14:11.667Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}