pola-rs/polars · error · ImportError

the graphviz `dot` binary should be on your PATH.(If not ins

Error message

the graphviz `dot` binary should be on your PATH.(If not installed you can download here: https://graphviz.org/download/)

What it means

ImportError from display_dot_graph (py-polars/src/polars/_utils/various.py:646-655), reached via LazyFrame.show_graph() and Expr.meta.show_graph(). Rendering the query-plan graph shells out to the graphviz `dot` executable (subprocess ['dot', '-Nshape=box', ...]); if the binary is not on PATH the FileNotFoundError is converted into this ImportError telling you to install graphviz. The pip package `graphviz` alone is not enough — the C system package provides the binary.

Source

Thrown at py-polars/src/polars/_utils/various.py:655

    output_type = (
        "svg"
        if (output_path is not None and str(output_path).endswith(".svg"))
        or _in_notebook()
        or _in_marimo_notebook()
        or "POLARS_DOT_SVG_VIEWER" in os.environ
        else "png"
    )

    try:
        graph = subprocess.check_output(
            ["dot", "-Nshape=box", "-T" + output_type], input=f"{dot}".encode()
        )
    except (ImportError, FileNotFoundError):
        msg = (
            "the graphviz `dot` binary should be on your PATH."
            "(If not installed you can download here: https://graphviz.org/download/)"
        )
        raise ImportError(msg) from None

    if output_path:
        Path(output_path).write_bytes(graph)

    if not show:
        return None

    if _in_notebook():
        from IPython.display import SVG, display

        return display(SVG(graph))
    elif _in_marimo_notebook():
        import marimo as mo

        return mo.Html(f"{graph.decode()}")
    else:
        if (cmd := os.environ.get("POLARS_DOT_SVG_VIEWER", None)) is not None:
            import tempfile

View on GitHub (pinned to df599052da)

Solutions

  1. Install the system package: apt-get install graphviz / brew install graphviz / apk add graphviz
  2. If you only need the plan text, call lf.show_graph(raw_output=True) to get the DOT string without invoking dot, or use lf.explain()
  3. Persist the DOT and render elsewhere: write the raw_output string to a .dot file and render on a machine with graphviz
  4. In Dockerfiles add the graphviz package to the image

Example fix

# before
lf.show_graph()  # ImportError: dot not on PATH

# after (no binary needed)
dot_source = lf.show_graph(raw_output=True)
Path('plan.dot').write_text(dot_source)

# and in the image: RUN apt-get update && apt-get install -y graphviz
Defensive patterns

Strategy: validation

Validate before calling

import shutil

def dot_available() -> bool:
    return shutil.which('dot') is not None

Try / catch

try:
    lf.show_graph(figsize=(16, 12))
except ImportError as e:
    if 'dot' in str(e):
        print(lf.explain())  # textual plan fallback
    else:
        raise

Prevention

When it happens

Trigger: lf.show_graph() or expr.meta.show_graph() on a machine without the graphviz system package; slim Docker images (python:*-slim, distroless) where graphviz was never installed; fresh CI runners.

Common situations: Debugging lazy query plans in notebooks after a container rebuild; `pip install graphviz` performed instead of the system install; PATH modifications in venv/conda that shadow or drop the binary.

Related errors


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