{"record":{"id":"f59079f2854da89e","repo":"pola-rs/polars","slug":"altair-5-4-0-is-required-for-plot-f59079","errorCode":null,"errorMessage":"altair>=5.4.0 is required for `.plot`","messagePattern":"altair>=5\\.4\\.0 is required for `\\.plot`","errorType":"exception","errorClass":"ModuleUpgradeRequiredError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/series/series.py","lineNumber":466,"sourceCode":"\n        Examples\n        --------\n        Histogram:\n\n        >>> s = pl.Series([1, 4, 4, 6, 2, 4, 3, 5, 5, 7, 1])\n        >>> s.plot.hist()  # doctest: +SKIP\n\n        KDE plot:\n\n        >>> s.plot.kde()  # doctest: +SKIP\n\n        Line plot:\n\n        >>> s.plot.line()  # doctest: +SKIP\n        \"\"\"  # noqa: W505\n        if not _ALTAIR_AVAILABLE or parse_version(altair.__version__) < (5, 4, 0):\n            msg = \"altair>=5.4.0 is required for `.plot`\"\n            raise ModuleUpgradeRequiredError(msg)\n        return SeriesPlot(self)\n\n    @classmethod\n    def _from_pyseries(cls, pyseries: PySeries) -> Self:\n        series = cls.__new__(cls)\n        series._s = pyseries\n        return series\n\n    @classmethod\n    @deprecated(\n        \"`_import_from_c` is deprecated; use `_import_arrow_from_c` instead. If \"\n        \"you are using an extension, please compile it with the latest 'pyo3-polars'\"\n    )\n    def _import_from_c(cls, name: str_, pointers: list_[tuple[int, int]]) -> Self:\n        # `_import_from_c` was deprecated in 1.3\n        return cls._from_pyseries(PySeries._import_arrow_from_c(name, pointers))\n\n    @classmethod","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/series/series.py#L448-L484","documentation":"Raised by Series.plot (py-polars/src/polars/series/series.py:466) when Altair is missing or older than 5.4.0. Polars implements the .plot namespace lazily and checks availability plus version (parse_version(altair.__version__) < (5,4,0)) on first access, throwing ModuleUpgradeRequiredError — a polars exception subclassing ModuleNotFoundError — so it also reads like an import error in logs.","triggerScenarios":"s.plot.hist() in an environment where altair is not installed, or with altair 4.x / early 5.x (< 5.4.0) installed. Common after upgrading polars in a stale env, or on CI where altair was never added because polars itself installs without it.","commonSituations":"Fresh clones / Docker images / CI runners where the optional altair dependency is absent; version pins that force an old altair; sharing notebooks across machines with different envs. The error surfaces only when .plot is accessed, so imports succeed and tests pass until plotting.","solutions":["Install or upgrade: pip install -U \"altair>=5.4.0\"","Pin altair in requirements/pyproject so environments are reproducible","In shared code, guard the plotting path: check importlib.util.find_spec('altair') and the version before calling .plot, and degrade gracefully (e.g. skip chart or fall back to matplotlib)"],"exampleFix":"# before (ModuleUpgradeRequiredError: altair>=5.4.0 is required for `.plot`)\ns.plot.hist()\n\n# after — install once:\n# pip install -U \"altair>=5.4.0\"\ns.plot.hist()","handlingStrategy":"validation","validationCode":"import importlib.util, importlib.metadata\n\ndef plot_available() -> bool:\n    if importlib.util.find_spec(\"altair\") is None:\n        return False\n    from packaging.version import Version\n    return Version(importlib.metadata.version(\"altair\")) >= Version(\"5.4.0\")\n\nif plot_available():\n    s.plot.hist()  # type: ignore[union-attr]\nelse:\n    print(\"altair>=5.4.0 not installed — skipping chart\")","typeGuard":null,"tryCatchPattern":"try:\n    chart = s.plot.hist()\nexcept ModuleNotFoundError as e:  # ModuleUpgradeRequiredError subclasses this\n    if \"altair\" in str(e):\n        raise RuntimeError(\"run: pip install -U 'altair>=5.4.0'\") from e\n    raise","preventionTips":["Declare altair>=5.4.0 in your project dependencies if any code path uses .plot","Guard plotting entry points with a version check so reports degrade instead of crashing"],"tags":["polars","plotting","altair","environment","optional-dependency","version"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}