pathwaycom/pathway · error · ValueError
Cannot join table with itself. Use <table>.copy() as one of
Error message
Cannot join table with itself. Use <table>.copy() as one of the arguments of the join.
What it means
join() compares left == right and raises ValueError if both joinables are the same object, because a self-join would make column references on both sides ambiguous. The message tells you to pass <table>.copy() as one side so each side gets its own ColumnReference namespace.
Source
Thrown at python/pathway/internals/joins.py:1009
)
return (inner_table, final_mapping)
@staticmethod
def _table_join(
left: Joinable,
right: Joinable,
*on: expr.ColumnExpression,
mode: JoinMode,
id: expr.ColumnReference | None = None,
left_instance: expr.ColumnReference | None = None,
right_instance: expr.ColumnReference | None = None,
exact_match: bool = False, # if True do not optionalize output columns even if other than inner join is used
left_exactly_once: bool = False,
right_exactly_once: bool = False,
) -> JoinResult:
if left == right:
raise ValueError(
"Cannot join table with itself. Use <table>.copy() as one of the arguments of the join."
)
left_table, left_substitutions = left._substitutions()
right_table, right_substitutions = right._substitutions()
chained_join_desugaring = SubstitutionDesugaring(
{**left_substitutions, **right_substitutions}
)
if id is not None:
id = chained_join_desugaring.eval_expression(id)
id_column = id._column
else:
id_column = None
common_column_names: StableSet[str] = StableSet()
if left_instance is not None and right_instance is not None:View on GitHub (pinned to fa2f74a464)
Solutions
- Copy one side: right = t.copy() then t.join(right, t.k == right.k)
- Use two independently-built (even identical) connector/table objects if a copy is not desired
Example fix
# before res = t.join(t, t.k == t.k) # after t_right = t.copy() res = t.join(t_right, t.k == t_right.k)
Defensive patterns
Strategy: validation
Validate before calling
def safe_self_join(t, cond_builder):
t2 = t.copy()
return t.join(t2, cond_builder(t, t2))
# or pre-check: assert left is not right and left != right before calling join Prevention
- For self-joins, always materialize right = t.copy() first
- After refactors, verify the two join arguments are distinct objects, not aliases
When it happens
Trigger: t.join(t, t.k == t.k) — literally passing the same Table object as both left and right (also via join_inner/join_left/join_right sugar).
Common situations: Self-joins for pair/key matching (e.g. finding rows sharing a key within one table); refactor renaming two variables that end up aliasing the same table object.
Related errors
- Join received extra kwargs. You probably want to use TableLi
- Cannot assign id's for this join type.
- Expected a ColumnReference, found a string. Did you mean thi
- In JoinResult.groupby() all arguments have to be a ColumnRef
- In JoinResult.reduce() all positional arguments have to be a
AI-assisted analysis of pathwaycom/pathway@fa2f74a464 (2026-08-15).
Data as JSON: /api/errors/aee6994c1b40ce51.
Report an issue: GitHub.