{"record":{"id":"a33028bfcf4ec8df","repo":"pathwaycom/pathway","slug":"cannot-perform-pathway-coalesce-on-columns-of-type","errorCode":null,"errorMessage":"Cannot perform pathway.coalesce on columns of types {[dtype.typehint for dtype in dtypes]}.","messagePattern":"Cannot perform pathway\\.coalesce on columns of types (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/pathway/internals/type_interpreter.py","lineNumber":398,"sourceCode":"        self._check_for_disallowed_types(\"pathway.coalesce\", *dtypes)\n        ret_type = dtypes[0]\n        non_optional_arg = False\n        for dtype in dtypes:\n            try:\n                ret_type = dt.types_lca(dtype, ret_type, raising=True)\n            except TypeError:\n                raise TypeError(\n                    \"Incompatible types in for a coalesce expression.\\n\"\n                    + f\"The types are: {dtypes}. \"\n                    + \"You might try casting the expressions to Any type to circumvent this, \"\n                    + \"but this is most probably an error.\"\n                )\n            if not isinstance(dtype, dt.Optional):\n                # FIXME: do we want to be more radical and return now?\n                # Maybe with a warning that some args are skipped?\n                non_optional_arg = True\n        if ret_type is dt.ANY and any(dtype is not dt.ANY for dtype in dtypes):\n            raise TypeError(\n                f\"Cannot perform pathway.coalesce on columns of types {[dtype.typehint for dtype in dtypes]}.\"\n            )\n        ret_type = dt.unoptionalize(ret_type) if non_optional_arg else ret_type\n        return _wrap(expression, ret_type)\n\n    def eval_require(\n        self,\n        expression: expr.RequireExpression,\n        state: TypeInterpreterState | None = None,\n        **kwargs,\n    ) -> expr.RequireExpression:\n        assert state is not None\n        args = [\n            self.eval_expression(arg, state=state, **kwargs) for arg in expression._args\n        ]\n        arg_dtypes = [arg._dtype for arg in args]\n        new_state = state.with_new_col(\n            [arg for arg in expression._args if isinstance(arg, expr.ColumnReference)]","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/internals/type_interpreter.py#L380-L416","documentation":"Raised when pw.coalesce produces a least-common-ancestor of Any while at least one argument is not Any. This means the dtypes could not be meaningfully unified (the LCA collapsed to Any), which Pathway treats as an error rather than silently returning an untyped column; the message lists the typehints of all arguments.","triggerScenarios":"pw.coalesce over columns whose only common ancestor is Any, e.g. an int column with a Json column, or a DateTime with a list column; mixing Json with concrete scalars; tuples of different shapes.","commonSituations":"Coalescing a parsed column with a raw Json fallback; merging heterogeneous columns from different sources under the assumption they are the same; Optional columns of unrelated payload types.","solutions":["Cast the heterogeneous argument to the concrete type first (e.g. pw.this.json_col.astype(str)) so the LCA becomes concrete","Restructure so fallback columns share the dtype of the primary column (fix source schemas)","Use a chain of pw.if_else/is_not_none if the columns genuinely have different types and different semantics","As a last resort, cast all arguments to Any — accepting loss of type checking"],"exampleFix":"# before\nv = pw.coalesce(pw.this.int_col, pw.this.json_col)  # LCA collapses to Any\n\n# after\nv = pw.coalesce(pw.this.int_col, pw.this.json_col.astype(int))","handlingStrategy":"type-guard","validationCode":"import pathway as pw\n\ndef coalesce_lca_is_concrete(dtypes) -> bool:\n    try:\n        ret = dtypes[0]\n        for d in dtypes[1:]:\n            ret = pw.typehints.lca(d, ret)\n        return ret is not None and not ret.equivalent_to(pw.typehints.Any())\n    except TypeError:\n        return False","typeGuard":"def lca_not_any(*dtypes) -> bool:\n    import pathway as pw\n    try:\n        ret = dtypes[0]\n        for d in dtypes[1:]:\n            ret = pw.typehints.lca(d, ret)\n        return not ret.equivalent_to(pw.typehints.Any())\n    except TypeError:\n        return False","tryCatchPattern":"try:\n    v = pw.coalesce(*cols)\nexcept TypeError:\n    v = pw.coalesce(*[c.astype(target) for c in cols])","preventionTips":["Never coalesce Json columns directly with concrete scalars; cast first","Unify the dtype of the same logical field across all inputs","Add a schema equality assertion test across connectors"],"tags":["pathway","type-checking","coalesce","any-type","typeerror"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}