{"record":{"id":"bc1d2f7f071d6f93","repo":"pathwaycom/pathway","slug":"join-condition-should-be-of-form-left-table-col","errorCode":null,"errorMessage":"join condition should be of form <left_table>.<column> == <right_table>.<column>","messagePattern":"join condition should be of form <left_table>\\.<column> == <right_table>\\.<column>","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/internals/joins.py","lineNumber":1131,"sourceCode":"            columns_mapping,\n            left_table,\n            right_table,\n            left,\n            right,\n            substitution,\n            common_column_names,\n            mode,\n        )\n\n\ndef validate_shape(cond: expr.ColumnExpression) -> expr.ColumnBinaryOpExpression:\n    if (\n        not isinstance(cond, expr.ColumnBinaryOpExpression)\n        or cond._operator != op.eq\n        or not isinstance(cond._left, expr.ColumnReference)\n        or not isinstance(cond._right, expr.ColumnReference)\n    ):\n        raise ValueError(\n            \"join condition should be of form <left_table>.<column> == <right_table>.<column>\"\n        )\n    return cond\n\n\ndef validate_join_condition(\n    cond: expr.ColumnExpression, left: Table, right: Table\n) -> tuple[expr.ColumnReference, expr.ColumnReference, expr.ColumnBinaryOpExpression]:\n    cond = validate_shape(cond)\n    try:\n        eval_type(cond)\n    except TypeError:\n        raise TypeError(\n            \"Incompatible types in a join condition.\\n\"\n            + f\"The types are: {eval_type(cond._left)} and {eval_type(cond._right)}. \"\n            + \"You might try casting the respective columns to Any type to circumvent this,\"\n            + \" but this is most probably an error.\"\n        )","sourceCodeStart":1113,"sourceCodeEnd":1149,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/internals/joins.py#L1113-L1149","documentation":"validate_shape enforces the structural contract of join conditions: cond must be a ColumnBinaryOpExpression using the == operator with a ColumnReference on each side (left, right). Anything else — a single column, <, <=, .isna(), a function call, chained comparisons — raises ValueError demanding the <left_table>.<column> == <right_table>.<column> form.","triggerScenarios":"t1.join(t2, t1.a) (bare column); t1.join(t2, t1.a < t2.b); t1.join(t2, (t1.a == t2.a) & (t1.c == t2.c)) — multiple conditions must be passed as separate *on args, not combined with &.","commonSituations":"SQL/pandas merge habits with arbitrary boolean predicates; trying compound conditions with & instead of varargs; inequality joins (unsupported).","solutions":["Rewrite the condition as a single equality between two column references","Pass multiple equality conditions as separate arguments: t1.join(t2, t1.a == t2.a, t1.c == t2.c)","For non-equality logic, pre-filter tables or apply the predicate in a later select/with_columns step"],"exampleFix":"# before\nres = t1.join(t2, (t1.a == t2.a) & (t1.c == t2.c))\n\n# after\nres = t1.join(t2, t1.a == t2.a, t1.c == t2.c)","handlingStrategy":"type-guard","validationCode":"from pathway.internals import expr, op\n\ndef is_eq_of_refs(cond) -> bool:\n    return (\n        isinstance(cond, expr.ColumnBinaryOpExpression)\n        and cond._operator == op.eq\n        and isinstance(cond._left, expr.ColumnReference)\n        and isinstance(cond._right, expr.ColumnReference)\n    )","typeGuard":"from pathway.internals import expr, op\n\ndef is_valid_join_condition(cond) -> bool:\n    return (\n        isinstance(cond, expr.ColumnBinaryOpExpression)\n        and cond._operator == op.eq\n        and isinstance(cond._left, expr.ColumnReference)\n        and isinstance(cond._right, expr.ColumnReference)\n    )","tryCatchPattern":null,"preventionTips":["One equality per argument; pass multiple conditions as separate *on args, never combined with &","Non-equality predicates belong in filter/where or a post-join with_columns"],"tags":["pathway","join","condition","validation","api-misuse"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}