pola-rs/polars · error · TypeError

invalid plan stage '{plan_stage}'

Error message

invalid plan stage '{plan_stage}'

What it means

LazyFrame.show_graph() accepts plan_stage of only 'ir' (logical plan) or 'physical' (executed physical plan). Any other value raises TypeError. The physical stage additionally branches on the engine: streaming engines render the streaming physical plan, others the regular one.

Source

Thrown at py-polars/src/polars/lazyframe/frame.py:1596

        if plan_stage is None:
            warnings.warn(
                "The default value of `plan_stage` will change from 'ir' to 'physical' in Polars 2.0. "
                'Explicitly set `plan_stage="ir"` to suppress this warning.',
                category=FutureWarning,
                stacklevel=find_stacklevel(),
            )
            plan_stage = "ir"

        if plan_stage == "ir":
            dot = _ldf.to_dot(optimized)
        elif plan_stage == "physical":
            if engine_.plan_engine == "streaming":
                dot = _ldf.to_dot_streaming_phys(optimized)
            else:
                dot = _ldf.to_dot(optimized)
        else:
            error_msg = f"invalid plan stage '{plan_stage}'"
            raise TypeError(error_msg)

        return display_dot_graph(
            dot=dot,
            show=show,
            output_path=output_path,
            raw_output=raw_output,
            figsize=figsize,
        )

    def inspect(self, fmt: str = "{}") -> LazyFrame:
        """
        Inspect a node in the computation graph.

        Print the value that this node in the computation graph evaluates to and pass on
        the value.

        .. engine-support:: in-memory

View on GitHub (pinned to df599052da)

Solutions

  1. Use plan_stage='ir' for the logical plan view
  2. Use plan_stage='physical' for the physical plan
  3. Check the value at runtime for typos or None
  4. Prefer lf.explain() when you only need the plan as text

Example fix

# before
lf.show_graph(plan_stage='optimized')

# after
lf.show_graph(plan_stage='ir')
Defensive patterns

Strategy: validation

Validate before calling

plan_stage = plan_stage if plan_stage in ('ir', 'physical') else 'ir'
lf.show_graph(plan_stage=plan_stage)

Type guard

def is_valid_plan_stage(stage: str) -> bool:
    return stage in {'ir', 'physical'}

Prevention

When it happens

Trigger: Calling lf.show_graph(plan_stage='optimized'), 'logical', 'dag', or None. Passing a variable that defaulted incorrectly, or using a value valid in a different polars version or in LazyFrame.explain() contexts.

Common situations: Typos; code written against older/newer APIs where stage names differed; interactive debugging of query plans.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/79c8524273c4940f. Report an issue: GitHub.