pathwaycom/pathway · error · TypeError

type of default {default_type.typehint} is not compatible wi

Error message

type of default {default_type.typehint} is not compatible with {target_type.typehint}.

What it means

Raised by the type interpreter when pw.unwrap(...) is given a default whose dtype is not a subtype of the conversion's target return type. unwrap(default=...) must return a value compatible with the type the JSON is converted to; e.g. unwrapping a JSON field typed as int with default="" (str default) fails this check.

Source

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

        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)

    def eval_declare(
        self,
        expression: expr.DeclareTypeExpression,
        state: TypeInterpreterState | None = None,
        **kwargs,
    ) -> expr.DeclareTypeExpression:
        expression = super().eval_declare(expression, state=state, **kwargs)

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Match the default's Python type to the field's converted type: unwrap(default=0) for int fields, unwrap(default="") for str fields
  2. Use None (with optional=... semantics) as default, which is always allowed since None-typed defaults are skipped by the check
  3. Re-check the JSON schema of the field (what unwrap will produce) and align the default literal

Example fix

# before
v = pw.this.payload.unwrap(default="")  # field unwraps to int

# after
v = pw.this.payload.unwrap(default=0)
# or
v = pw.this.payload.unwrap(default=None)
Defensive patterns

Strategy: validation

Validate before calling

import pathway as pw

def default_matches(default, target_type_example):
    return default is None or type(default) is type(target_type_example)

# e.g. only pass default=0 when the field unwraps to int
default = 0 if field_is_int else ("" if field_is_str else None)

Type guard

def default_ok(default, python_type) -> bool:
    return default is None or isinstance(default, python_type)

Try / catch

try:
    v = pw.this.payload.unwrap(default=0)
except TypeError:
    v = pw.this.payload.unwrap(default=None)  # always-allowed default

Prevention

When it happens

Trigger: pw.this.col.unwrap(default="none") where the JSON field's converted type is int/float; unwrap(default=0) on a field declared to unwrap into str; passing a bool default for a str field.

Common situations: Copy-pasting defaults between unwrap calls with different field types; assuming defaults are untyped sentinels; defaults used to mask missing keys without matching the field's JSON schema.

Related errors


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