pathwaycom/pathway · error · ValueError
iterated table not marked as 'iterate_universe' changed its
Error message
iterated table not marked as 'iterate_universe' changed its universe
What it means
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.
Source
Thrown at python/pathway/internals/operator.py:416
iterated_with_universe_copy
)
self.extra_copy = input_copy.subtract_keys(self.iterated_copy)
# prepare iteration result
self.result_iterated_with_universe = result.intersect_keys(
iterated_with_universe_copy
)
self.result_iterated = result.subtract_keys(iterated_with_universe_copy)
# materialize output
output = type(arg_tuple).empty()
for name, table in result.items():
if name in self.iterated_with_universe_copy:
universe = Universe()
elif table._universe == input_copy[name]._universe:
universe = input[name]._universe
else:
raise ValueError(
"iterated table not marked as 'iterate_universe' changed its universe"
)
output[name] = table._materialize(universe)
output = output.with_same_order(
self.result_iterated + self.result_iterated_with_universe
)
self._prepare_inputs(input)
self._prepare_outputs(output)
return output.to_output()
def _copy_input_table(self, name: str, table: tables.Table, unique: bool):
if unique:
universe = Universe()
else:
universe = self._universe_mapping[table._universe]
table_copy = table._materialize(universe)
table_copy._set_source(OutputHandle(self, name, table_copy))View on GitHub (pinned to fa2f74a464)
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.
Example fix
# before result = pw.iterate(step, edges=edges, frontier=frontier) # step filters frontier # after result = pw.iterate(step, edges=edges, frontier=pw.iterate_universe(frontier))
Defensive patterns
Strategy: validation
Validate before calling
import pathway as pw
def plain_args_keep_universe(inputs: dict, outputs: dict) -> bool:
return all(
outputs[name]._universe == inputs[name]._universe
for name in inputs
if name in outputs
) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Writing iterative graph algorithms where each step prunes finished nodes; forgetting to mark the shrinking table with pw.iterate_universe when calling pw.iterate.
Related errors
- not all arguments marked as iterated returned from iteration
- {name} has to be a Table instead of {type(arg)}
- output: {result_schema} of the iterated function does not c
- transformer has no attribute `{table_name}`
- You cannot use {dep.to_column_expression()} in this context.
AI-assisted analysis of pathwaycom/pathway@fa2f74a464 (2026-08-15).
Data as JSON: /api/errors/c232ff1c89c8ef8f.
Report an issue: GitHub.