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
- Declare the column as Json in the schema (value: pw.Json) so unwrap() is valid
- Remove the unwrap() call if the column already has a concrete type — it is only for Json columns
- 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
- Type JSON payload fields as pw.Json in schemas from day one
- Remember unwrap is only for Json columns; concrete columns need no unwrap
- Keep a project-wide convention: parse (pw.json) -> unwrap -> use
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
- type of default {default_type.typehint} is not compatible wi
- Pathway does not support using unary operator {operator_fun.
- Pathway does not support using binary operator {operator.__n
- Cannot change type from {right} to {left}.\npw.`declare_type
- Incompatible types in for a coalesce expression.\nThe types
AI-assisted analysis of pathwaycom/pathway@fa2f74a464 (2026-08-15).
Data as JSON: /api/errors/292d1afd18bdbc87.
Report an issue: GitHub.