pathwaycom/pathway · error · TypeError

Cannot perform pathway.if_else on columns of types {then_dty

Error message

Cannot perform pathway.if_else on columns of types {then_dtype.typehint} and {else_dtype.typehint}.

What it means

Raised when the then/else branches of pw.if_else have dtypes with no common ancestor: dt.types_lca(then, else, raising=True) throws and the interpreter converts it into a TypeError naming both typehints. Both branches must unify to one result dtype.

Source

Thrown at python/pathway/internals/type_interpreter.py:481

            )
        else:
            then_ = self.eval_expression(expression._then, state=state, **kwargs)

        if isinstance(if_, expr.IsNoneExpression) and isinstance(
            if_._expr, expr.ColumnReference
        ):
            else_ = self.eval_expression(
                expression._else, state=state.with_new_col([if_._expr], **kwargs)
            )
        else:
            else_ = self.eval_expression(expression._else, state=state, **kwargs)

        then_dtype = then_._dtype
        else_dtype = else_._dtype
        try:
            lca = dt.types_lca(then_dtype, else_dtype, raising=True)
        except TypeError:
            raise TypeError(
                f"Cannot perform pathway.if_else on columns of types {then_dtype.typehint} and {else_dtype.typehint}."
            )
        if lca is dt.ANY:
            raise TypeError(
                f"Cannot perform pathway.if_else on columns of types {then_dtype.typehint} and {else_dtype.typehint}."
            )
        expression = expr.IfElseExpression(if_, then_, else_)
        return _wrap(expression, lca)

    def eval_make_tuple(
        self,
        expression: expr.MakeTupleExpression,
        state: TypeInterpreterState | None = None,
        **kwargs,
    ) -> expr.MakeTupleExpression:
        expression = super().eval_make_tuple(expression, state=state, **kwargs)
        dtypes = tuple(arg._dtype for arg in expression._args)
        self._check_for_disallowed_types("pathway.make_tuple", *dtypes)

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Cast both branches to a common type: pw.if_else(cond, pw.this.a.astype(str), pw.this.b.astype(str))
  2. Use matching literal types in both branches (e.g. None handled via Optional-aware expressions or equal-typed sentinels)
  3. Align source schemas so paired columns share dtype
  4. If mixing is deliberate, cast both to Any (documented escape hatch, loses checking)

Example fix

# before
v = pw.if_else(pw.this.ok, pw.this.code, pw.this.label)  # int vs str

# after
v = pw.if_else(pw.this.ok, pw.this.code.astype(str), pw.this.label)
Defensive patterns

Strategy: type-guard

Validate before calling

import pathway as pw

def branches_compatible(then_dtype, else_dtype) -> bool:
    try:
        lca = pw.typehints.lca(then_dtype, else_dtype)
        return lca is not None and not lca.equivalent_to(pw.typehints.Any())
    except TypeError:
        return False

Type guard

def branches_same_type(then_dtype, else_dtype) -> bool:
    return then_dtype.equivalent_to(else_dtype)

Try / catch

try:
    v = pw.if_else(cond, x, y)
except TypeError:
    v = pw.if_else(cond, x.astype(str), y.astype(str))

Prevention

When it happens

Trigger: pw.if_else(cond, pw.this.int_col, pw.this.str_col); branches of different literal types (1 vs "1"); one branch returning DateTime and the other None-untyped; branches whose LCA only exists for identical shapes of tuples/lists and those shapes differ.

Common situations: Returning type-inconsistent literals from branches (0 vs None vs ""); joining values from columns with divergent schemas; forgetting to cast one branch after a schema change.

Related errors


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