{"record":{"id":"25bdecd5f8150b84","repo":"pathwaycom/pathway","slug":"universes-of-the-arguments-of-table-concat-have","errorCode":null,"errorMessage":"Universes of the arguments of Table.concat() have to be disjoint.\nConsider using Table.promise_universes_are_disjoint() to assert it.\n(However, untrue assertion might result in runtime errors.)","messagePattern":"Universes of the arguments of Table\\.concat\\(\\) have to be disjoint\\.\nConsider using Table\\.promise_universes_are_disjoint\\(\\) to assert it\\.\n\\(However, untrue assertion might result in runtime errors\\.\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/internals/table.py","lineNumber":1675,"sourceCode":"            )\n        id_type = _types_lca_with_error(\n            *[arg.schema._id_dtype for arg in all_args],\n            function_name=\"a concat\",\n            pointers=True,\n        )\n\n        return Table._concat(\n            *[tab.cast_to_types(**schema).update_id_type(id_type) for tab in all_args]\n        )\n\n    @trace_user_frame\n    @contextualized_operator\n    def _concat(self, *others: Table[TSchema]) -> Table[TSchema]:\n        union_ids = (self._id_column, *(other._id_column for other in others))\n        if not self._get_universe_solver().query_are_disjoint(\n            *(c.universe for c in union_ids)\n        ):\n            raise ValueError(\n                \"Universes of the arguments of Table.concat() have to be disjoint.\\n\"\n                + \"Consider using Table.promise_universes_are_disjoint() to assert it.\\n\"\n                + \"(However, untrue assertion might result in runtime errors.)\"\n            )\n        context = clmn.ConcatUnsafeContext(\n            union_ids=union_ids,\n            updates=tuple(\n                {col_name: other._columns[col_name] for col_name in self.keys()}\n                for other in others\n            ),\n        )\n        return self._table_with_context(context)\n\n    @trace_user_frame\n    @check_arg_types\n    def update_cells(self, other: Table, _stacklevel: int = 1) -> Table:\n        \"\"\"Updates cells of `self`, breaking ties in favor of the values in `other`.\n","sourceCodeStart":1657,"sourceCodeEnd":1693,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/internals/table.py#L1657-L1693","documentation":"Raised by Table._concat() when the universe solver cannot prove that the argument tables' row-id sets are pairwise disjoint. Vertical concatenation in Pathway is unsafe if two tables contain the same primary key, because the rows would collide. Pathway deliberately makes you assert disjointness explicitly.","triggerScenarios":"pw.Table.concat(t1, t2) where t1 and t2 may share ids (e.g. both derived from the same source, or ids generated from overlapping values); the solver returns query_are_disjoint(...) == False.","commonSituations":"Concatenating two streams derived from one upstream table (ids inherited); combining tables whose ids both come from pointer_from_string over overlapping keys; new users expecting SQL UNION-like semantics.","solutions":["If the tables are provably disjoint, assert it: pw.Table.concat(t1.promise_universes_are_disjoint(), t2) — note the assertion only affects t2's relation to earlier args","Regenerate ids on one side so they cannot collide: t2 = t2.with_id_from(...) or t2 = t2.with_id(pw.this.id + offset)","If you actually want UNION-with-collision semantics, use update_cells/update_rows composition or a join-based merge instead of concat","Verify overlap first with pw.debug.compute_and_print on both id sets in a small test"],"exampleFix":"# before\nt3 = pw.Table.concat(t1, t2)  # ValueError: universes not disjoint\n\n# after (only if truly disjoint!)\nt3 = pw.Table.concat(t1, t2.promise_universes_are_disjoint())\n# or force fresh ids\nt3 = pw.Table.concat(t1, t2.with_id_from(pw.this.make_ptr(t2.id, t2.name)))","handlingStrategy":"validation","validationCode":"# Only assert when ids provably cannot overlap (e.g. distinct key ranges)\ndef disjoint_concat(t1, t2):\n    return pw.Table.concat(t1, t2.promise_universes_are_disjoint())","typeGuard":null,"tryCatchPattern":"try:\n    t3 = pw.Table.concat(t1, t2)\nexcept ValueError as e:\n    if 'have to be disjoint' in str(e):\n        t3 = pw.Table.concat(t1, t2.with_id_from(\n            pw.this.make_ptr(pw.this.id, 'source2')\n        ))","preventionTips":["Never concat tables whose ids derive from the same upstream ids","Regenerate ids per branch before concat when in doubt","Reserve promise_universes_are_disjoint for provable disjointness — a false assertion causes runtime errors"],"tags":["pathway","universe","table-concat","disjoint"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}