pathwaycom/pathway · error · TypeError

Cannot change type from {right} to {left}.\npw.`declare_type

Error message

Cannot change type from {right} to {left}.\npw.`declare_type` should be used only for type narrowing or type extending.

What it means

Raised by the type interpreter for pw.declare_type expressions. declare_type may only narrow (declared subtype of actual) or widen (actual subtype of declared) a column's type; if the two dtypes are unrelated, Pathway refuses the cast because it would not be a sound up/down-cast and could hide real type errors.

Source

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

        if not expression._unwrap and (
            isinstance(default_type, dt.Optional) or default_type == dt.NONE
        ):
            target_type = dt.Optional(target_type)

        return _wrap(expression, target_type)

    def eval_declare(
        self,
        expression: expr.DeclareTypeExpression,
        state: TypeInterpreterState | None = None,
        **kwargs,
    ) -> expr.DeclareTypeExpression:
        expression = super().eval_declare(expression, state=state, **kwargs)
        left = expression._return_type
        right = expression._expr._dtype
        if not (dt.dtype_issubclass(left, right) or dt.dtype_issubclass(right, left)):
            raise TypeError(
                f"Cannot change type from {right} to {left}.\n"
                + "pw.`declare_type` should be used only for type narrowing or type extending."
            )
        return _wrap(expression, expression._return_type)

    def eval_coalesce(
        self,
        expression: expr.CoalesceExpression,
        state: TypeInterpreterState | None = None,
        **kwargs,
    ) -> expr.CoalesceExpression:
        expression = super().eval_coalesce(expression, state=state, **kwargs)
        dtypes = [arg._dtype for arg in expression._args]
        self._check_for_disallowed_types("pathway.coalesce", *dtypes)
        ret_type = dtypes[0]
        non_optional_arg = False
        for dtype in dtypes:
            try:

View on GitHub (pinned to fa2f74a464)

Solutions

  1. For genuine conversion (e.g. str to DateTime) use parsing functions: pw.this.col.strptime(...) / pw.utc or astype/cast_to instead of declare_type
  2. For narrowing, make sure the declared type is a subtype of the current one (e.g. Any -> int)
  3. For widening, declare a supertype of the current dtype
  4. If types are truly unrelated, insert an explicit conversion expression first, then declare_type if still needed

Example fix

# before
v = pw.declare_type(datetime, pw.this.ts)  # pw.this.ts is str -> unrelated, raises

# after
v = pw.this.ts.dt.strptime("%Y-%m-%d %H:%M:%S")  # real conversion
Defensive patterns

Strategy: type-guard

Validate before calling

import pathway as pw

def declare_is_sound(declared, actual) -> bool:
    return (
        declared.equivalent_to(actual)
        or pw.typehints.issubtype(declared, actual)
        or pw.typehints.issubtype(actual, declared)
    )

Type guard

def declare_is_sound(declared, actual) -> bool:
    import pathway as pw
    return pw.typehints.issubtype(declared, actual) or pw.typehints.issubtype(actual, declared)

Try / catch

try:
    v = pw.declare_type(T, pw.this.col)
except TypeError:
    v = pw.this.col.astype(T)  # real conversion instead of declaration

Prevention

When it happens

Trigger: pw.declare_type(str, pw.this.int_col) where int_col is int (unrelated types); declaring a column as DateTime when it is currently str without going through proper parsing (pw.utc); narrowing pw.Json to a wrong concrete type direction.

Common situations: Trying to use declare_type as a generic cast replacement for astype/cast_to; connector schemas that infer str while the user wants DateTime directly; porting pandas astype calls.

Related errors


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