pathwaycom/pathway · error · ValueError

invalid expression in restricted context

Error message

invalid expression in restricted context

What it means

A TableRestrictedRowwiseContext (e.g. expressions inside table.restrict or similar table-scoped operations) only permits column references belonging to its own table. eval_column_val checks expression.table against the context table and raises this ValueError when a reference from a different table leaks in — the operation cannot compute over columns outside its scope.

Source

Thrown at python/pathway/internals/graph_runner/expression_evaluator.py:842

                return fun(*arg_values, **kwarg_values)

            return wrapped, (*args, *kwargs.values())
        else:
            return fun, args


class TableRestrictedRowwiseEvaluator(
    RowwiseEvaluator, context_type=clmn.TableRestrictedRowwiseContext
):
    context: clmn.TableRestrictedRowwiseContext

    def eval_column_val(
        self,
        expression: expr.ColumnReference,
        eval_state: RowwiseEvalState | None = None,
    ):
        if expression.table != self.context.table:
            raise ValueError("invalid expression in restricted context")
        return super().eval_column_val(expression, eval_state)


class FilterEvaluator(ExpressionEvaluator, context_type=clmn.FilterContext):
    context: clmn.FilterContext

    def run(self, output_storage: Storage) -> api.Table:
        input_storage = self.state.get_storage(self.context.input_universe())
        filtering_column_path = input_storage.get_path(self.context.filtering_column)
        properties = self._table_properties(output_storage)
        return self.scope.filter_table(
            self.state.get_table(input_storage._universe),
            filtering_column_path,
            properties,
        )


class ForgetEvaluator(ExpressionEvaluator, context_type=clmn.ForgetContext):

View on GitHub (pinned to fa2f74a464)

Solutions

  1. Perform the cross-table access in the join/select where both tables are in scope, then run the restricted operation on the result
  2. Inside the restricted context, reference only columns of the context table (pw.this.* or that table's references)
  3. If you need a constant/foreign value, materialize it as a column in the scoped table first (e.g. via a join or table.with_columns) before restriction

Example fix

// before
result = t1.restrict(...expressions using t2.col...)
// after
joined = t1.join(t2, t1.k == t2.k).select(t1.val, extra=t2.col)
result = joined.restrict(...)  # only joined.* referenced inside
Defensive patterns

Strategy: validation

Validate before calling

def refs_only_context_table(expressions, context_table) -> bool:
    return all(getattr(e, "table", context_table) == context_table for e in expressions)

Type guard

from pathway.internals.expression import ColumnReference

def ref_belongs_to(ref: ColumnReference, table) -> bool:
    return isinstance(ref, ColumnReference) and ref.table == table

Prevention

When it happens

Trigger: Inside a restricted-context callback, referencing another table's column: table.restrict(...) bodies or select-with-join contexts that use pw.this plus a captured column from a second table; passing join result expressions back into one side's restricted operation; closures capturing table2.col while operating on table1.

Common situations: Refactoring joins: authors pull a column reference from the wrong side; copy-pasting a select body from a join into a single-table restricted operation; mixing pw.this with explicitly-named table references inside restricted APIs.

Related errors


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