{"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":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/lazyframe/frame.py","lineNumber":6474,"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":6456,"sourceCodeEnd":6492,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/lazyframe/frame.py#L6456-L6492","documentation":"LazyFrame.join() needs the join key(s): either on= or the pair left_on=/right_on=. Supplying none of them raises ValueError — unlike some engines, polars does not infer or default to matching on common column names here.","triggerScenarios":"lf.join(other, how='inner') with no keys; keys expected to be picked up from a kwargs dict that was empty; refactoring that dropped the on= argument.","commonSituations":"Pipeline code where join keys come from config and the config entry is missing; quick experiments omitting keys.","solutions":["Add on='key' for same-named keys, or left_on=/right_on= for differing names","Validate config before building the join: fail fast with a clear config error","For Cartesian products use how='cross' explicitly (which takes no keys)"],"exampleFix":"# before\nlf.join(other, how='inner')\n\n# after\nlf.join(other, on='id', how='inner')","handlingStrategy":"validation","validationCode":"if on is None and left_on is None and right_on is None:\n    raise ValueError('config missing join key: set on= or left_on=/right_on=')\nlf.join(other, on=on, left_on=left_on, right_on=right_on)","typeGuard":"def has_join_key(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":null,"preventionTips":["Validate join config at load time, not at execution time","Include join keys in pipeline config schema validation","Write a unit test that every configured join has keys"],"tags":["polars","lazyframe","join","missing-argument"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}