pathwaycom/pathway · error · TypeError

{expression!r} can only be applied to JSON columns, but colu

Error message

{expression!r} can only be applied to JSON columns, but column has type {expression._expr._dtype.typehint}.

What it means

Raised by the type interpreter for a ConvertExpression (pw.unwrap) applied to a column whose dtype is not Json (after unoptionalize). unwrap() converts JSON-typed values into concrete Python values; using it on str, int, or any non-Json column is a type error detected at graph construction.

Source

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

        expression: expr.CastExpression,
        state: TypeInterpreterState | None = None,
        **kwargs,
    ) -> expr.CastExpression:
        expression = super().eval_cast(expression, state=state, **kwargs)
        return _wrap(expression, expression._return_type)

    def eval_convert(
        self,
        expression: expr.ConvertExpression,
        state: TypeInterpreterState | None = None,
        **kwargs,
    ) -> expr.ConvertExpression:
        expression = super().eval_convert(expression, state=state, **kwargs)
        target_type = expression._return_type
        default_type = expression._default._dtype

        if dt.unoptionalize(expression._expr._dtype) is not dt.JSON:
            raise TypeError(
                f"{expression!r} can only be applied to JSON columns, "
                f"but column has type {expression._expr._dtype.typehint}."
            )

        if default_type != dt.NONE and not dt.dtype_issubclass(
            dt.unoptionalize(default_type), target_type
        ):
            raise TypeError(
                f"type of default {default_type.typehint} "
                f"is not compatible with {target_type.typehint}."
            )

        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)

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Declare the column as Json in the schema (value: pw.Json) so unwrap() is valid
  2. Remove the unwrap() call if the column already has a concrete type — it is only for Json columns
  3. If the column is Any, cast to Json first (pw.cast_to(pw.Json)) then unwrap

Example fix

# before
class Input(pw.Schema):
    payload: str  # actually holds JSON
out = table.select(v=pw.this.payload.unwrap())  # TypeError: not a JSON column

# after
class Input(pw.Schema):
    payload: pw.Json
out = table.select(v=pw.this.payload.unwrap())
Defensive patterns

Strategy: type-guard

Validate before calling

import pathway as pw

def is_json_column(dtype) -> bool:
    return dtype.equivalent_to(pw.typehints.Json()) or dtype.unoptionalize().equivalent_to(pw.typehints.Json())

# only call unwrap when True

Type guard

def is_json_column(dtype) -> bool:
    import pathway as pw
    th = dtype.unoptionalize() if hasattr(dtype, "unoptionalize") else dtype
    return th.equivalent_to(pw.typehints.Json())

Try / catch

try:
    out = t.select(v=pw.this.col.unwrap())
except TypeError:
    out = t.select(v=pw.this.col)  # column already concrete; skip unwrap

Prevention

When it happens

Trigger: pw.this.col.unwrap() where col was typed as str/float/Any instead of Json; unwrapping a column produced by a connector with a plain schema; calling unwrap on the result of get() whose type is already concrete after conversion.

Common situations: JSON payloads ingested with a schema that declares fields as str instead of Json; forgetting that pw.json parses into Json dtype and applying unwrap twice; columns that were already cast away from Json earlier in the pipeline.

Related errors


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