pathwaycom/pathway · error · ValueError

Expected a ColumnReference, found a string. Did you mean thi

Error message

Expected a ColumnReference, found a string. Did you mean this.{arg} instead of {repr(arg)}?

What it means

JoinResult.groupby validates every positional argument: it must be an expr.ColumnReference. When a plain Python str is passed instead, ValueError suggests the likely intended form this.<arg> — e.g. groupby('owner') should be groupby(pw.this.owner) or table.owner. The string-specific branch exists purely to give an actionable hint.

Source

Thrown at python/pathway/internals/joins.py:850

        ... 3    80  Alice    2
        ... ''')
        >>> t2 = pw.debug.table_from_markdown('''
        ...     cost  owner  pet size
        ... 11   100  Alice    3    M
        ... 12    90    Bob    1    L
        ... 13    80    Tom    1   XL
        ... ''')
        >>> result = (t1.join(t2, t1.owner==t2.owner).groupby(pw.this.owner)
        ...     .reduce(pw.this.owner, pairs = pw.reducers.count()))
        >>> pw.debug.compute_and_print(result, include_id=False)
        owner | pairs
        Alice | 2
        Bob   | 1
        """
        for arg in args:
            if not isinstance(arg, expr.ColumnReference):
                if isinstance(arg, str):
                    raise ValueError(
                        f"Expected a ColumnReference, found a string. Did you mean this.{arg} instead of {repr(arg)}?"
                    )
                else:
                    raise ValueError(
                        "In JoinResult.groupby() all arguments have to be a ColumnReference."
                    )
        from pathway.internals.groupbys import GroupedJoinResult

        return GroupedJoinResult(
            _join_result=self,
            _args=args,
            _id=id,
        )

    @trace_user_frame
    @desugar
    @arg_handler(handler=reduce_args_handler)
    def reduce(

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Replace the string with a ColumnReference: pw.this.<col> or <table>.<col>
  2. When building dynamically, map names through getattr(table, name) instead of passing raw strings

Example fix

# before
res = t1.join(t2, t1.owner == t2.owner).groupby('owner')

# after
res = t1.join(t2, t1.owner == t2.owner).groupby(pw.this.owner)
Defensive patterns

Strategy: type-guard

Validate before calling

from pathway.internals import expr

def to_refs(table, names):
    refs = [getattr(table, n) if isinstance(n, str) else n for n in names]
    assert all(isinstance(r, expr.ColumnReference) for r in refs)
    return refs

Type guard

from pathway.internals import expr

def is_column_reference(x) -> bool:
    return isinstance(x, expr.ColumnReference)

Prevention

When it happens

Trigger: result = t1.join(t2, ...).groupby('colname') — passing column names as strings, as pandas/SQL allow.

Common situations: Porting pandas merge+groupby code; dynamically building groupby lists from string column names; muscle memory from dataframe APIs.

Related errors


AI-assisted analysis of pathwaycom/pathway@fa2f74a464 (2026-08-15). Data as JSON: /api/errors/0f78a0162256ac31. Report an issue: GitHub.