{"record":{"id":"c232ff1c89c8ef8f","repo":"pathwaycom/pathway","slug":"iterated-table-not-marked-as-iterate-universe-ch","errorCode":null,"errorMessage":"iterated table not marked as 'iterate_universe' changed its universe","messagePattern":"iterated table not marked as 'iterate_universe' changed its universe","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/pathway/internals/operator.py","lineNumber":416,"sourceCode":"            iterated_with_universe_copy\n        )\n        self.extra_copy = input_copy.subtract_keys(self.iterated_copy)\n\n        # prepare iteration result\n        self.result_iterated_with_universe = result.intersect_keys(\n            iterated_with_universe_copy\n        )\n        self.result_iterated = result.subtract_keys(iterated_with_universe_copy)\n\n        # materialize output\n        output = type(arg_tuple).empty()\n        for name, table in result.items():\n            if name in self.iterated_with_universe_copy:\n                universe = Universe()\n            elif table._universe == input_copy[name]._universe:\n                universe = input[name]._universe\n            else:\n                raise ValueError(\n                    \"iterated table not marked as 'iterate_universe' changed its universe\"\n                )\n            output[name] = table._materialize(universe)\n        output = output.with_same_order(\n            self.result_iterated + self.result_iterated_with_universe\n        )\n\n        self._prepare_inputs(input)\n        self._prepare_outputs(output)\n        return output.to_output()\n\n    def _copy_input_table(self, name: str, table: tables.Table, unique: bool):\n        if unique:\n            universe = Universe()\n        else:\n            universe = self._universe_mapping[table._universe]\n        table_copy = table._materialize(universe)\n        table_copy._set_source(OutputHandle(self, name, table_copy))","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/internals/operator.py#L398-L434","documentation":"In iterative transformers, an output table that was NOT marked with pw.iterate_universe must keep the same universe (set of row ids) as its corresponding input table between iteration steps. After calling the iteration logic, Pathway checks table._universe == input_copy[name]._universe; if a filter/join inside the step changed the row set, this ValueError fires because Pathway cannot reconcile the changed universe without the iterate_universe marker.","triggerScenarios":"A @pw.table_transformer iteration step that applies .filter(), .flatten(), a join that drops rows, or .with_id() on an argument passed as a plain pw.Table (not wrapped in pw.iterate_universe), while reusing the same argument name in the returned dict.","commonSituations":"Writing iterative graph algorithms where each step prunes finished nodes; forgetting to mark the shrinking table with pw.iterate_universe when calling pw.iterate.","solutions":["Wrap the argument whose universe changes with pw.iterate_universe(table) at the pw.iterate call site — that is exactly what the marker is for.","Or remove the universe-changing operation (filter/join/flatten) from the step so every plain table keeps its row set across steps.","If filtering is needed only for the final result, apply it after pw.iterate returns, not inside the step."],"exampleFix":"# before\nresult = pw.iterate(step, edges=edges, frontier=frontier)  # step filters frontier\n\n# after\nresult = pw.iterate(step, edges=edges, frontier=pw.iterate_universe(frontier))","handlingStrategy":"validation","validationCode":"import pathway as pw\n\ndef plain_args_keep_universe(inputs: dict, outputs: dict) -> bool:\n    return all(\n        outputs[name]._universe == inputs[name]._universe\n        for name in inputs\n        if name in outputs\n    )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap any argument that a filter/join/flatten will shrink in pw.iterate_universe at the call site.","Do universe-changing operations after pw.iterate returns, never inside a plain-arg step."],"tags":["pathway","iteration","universe","table-transformer"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}