{"record":{"id":"70f197cbb06d2af1","repo":"mlflow/mlflow","slug":"unsupported-figure-object-type-type-figure","errorCode":null,"errorMessage":"Unsupported figure object type: '{type(figure)}'","messagePattern":"Unsupported figure object type: '(.+?)'","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"mlflow/tracking/client.py","lineNumber":3098,"sourceCode":"            # `is_matplotlib_figure` is executed only when `matplotlib` is found in `sys.modules`.\n            # This allows logging a `plotly` figure in an environment where `matplotlib` is not\n            # installed.\n            if \"matplotlib\" in sys.modules and _is_matplotlib_figure(figure):\n                figure.savefig(tmp_path, **save_kwargs)\n            elif \"plotly\" in sys.modules and _is_plotly_figure(figure):\n                file_extension = os.path.splitext(artifact_file)[1]\n                if file_extension == \".html\":\n                    save_kwargs.setdefault(\"include_plotlyjs\", \"cdn\")\n                    save_kwargs.setdefault(\"auto_open\", False)\n                    figure.write_html(tmp_path, **save_kwargs)\n                elif file_extension in [\".png\", \".jpeg\", \".webp\", \".svg\", \".pdf\"]:\n                    figure.write_image(tmp_path, **save_kwargs)\n                else:\n                    raise TypeError(\n                        f\"Unsupported file extension for plotly figure: '{file_extension}'\"\n                    )\n            else:\n                raise TypeError(f\"Unsupported figure object type: '{type(figure)}'\")\n\n    def log_image(\n        self,\n        run_id: str,\n        image: Union[\"numpy.ndarray\", \"PIL.Image.Image\", \"mlflow.Image\"],\n        artifact_file: str | None = None,\n        key: str | None = None,\n        step: int | None = None,\n        timestamp: int | None = None,\n        synchronous: bool | None = None,\n    ) -> None:\n        \"\"\"\n        Logs an image in MLflow, supporting two use cases:\n\n        1. Time-stepped image logging:\n            Ideal for tracking changes or progressions through iterative processes (e.g.,\n            during model training phases).\n","sourceCodeStart":3080,"sourceCodeEnd":3116,"githubUrl":"https://github.com/mlflow/mlflow/blob/6a27f2decc0b76eb1b54af31849784addb357dbc/mlflow/tracking/client.py#L3080-L3116","documentation":"log_figure() only accepts matplotlib figure objects and Plotly figure objects; anything else (including plain dicts, bokeh figures, or nested figures) raises this TypeError. The library cannot serialize an unknown figure type to an artifact file.","triggerScenarios":"client.log_figure(run_id, some_non_figure_object, \"fig.png\") where the object is not a matplotlib.figure.Figure or plotly figure (e.g., a seaborn axis-level object passed without .fig access, a bokeh figure, or a PIL image mistakenly routed to log_figure).","commonSituations":"Passing a PIL image or numpy array — those belong in log_image(); passing seaborn plots (some return axes, not figures); version changes where a custom plot library figure was expected to be supported but isn't.","solutions":["Convert to a supported type: for plotly use plotly.graph_objects.Figure; for matplotlib use matplotlib.figure.Figure (e.g., call .figure on a seaborn axis, or plt.gcf()).","For PIL images or numpy arrays, use client.log_image() instead of log_figure().","For unsupported libraries (bokeh, altair), export to HTML/PNG bytes yourself and log the file via log_artifact()."],"exampleFix":"// before\nclient.log_figure(run_id, ax, \"plot.png\")  # seaborn axes object\n\n// after\nclient.log_figure(run_id, ax.figure, \"plot.png\")","handlingStrategy":"type-guard","validationCode":"import matplotlib.figure\nfrom plotly.graph_objs import Figure\nif not isinstance(figure, (matplotlib.figure.Figure, Figure)):\n    raise TypeError(f\"log_figure accepts matplotlib/plotly figures, got {type(figure)}\")\nclient.log_figure(run_id, figure, artifact_file)","typeGuard":"def is_loggable_figure(fig) -> bool:\n    import matplotlib.figure\n    from plotly.graph_objs import Figure\n    return isinstance(fig, (matplotlib.figure.Figure, Figure))","tryCatchPattern":"try:\n    client.log_figure(run_id, figure, artifact_file)\nexcept TypeError as e:\n    if \"Unsupported figure object type\" in str(e):\n        client.log_artifact(run_id, export_figure_to_file(figure), artifact_file)\n    else:\n        raise","preventionTips":["Use log_image() for PIL images / numpy arrays, not log_figure().","For seaborn axis-level results, log ax.figure rather than ax.","Standardize on matplotlib Figure or plotly Figure objects before logging.","Validate figure type in your plotting helper before returning it for logging."],"tags":["mlflow","figure-logging","type-error","plotly","matplotlib"],"backgroundTag":"unsupported-object-type","analyzedSha":"6a27f2decc0b76eb1b54af31849784addb357dbc","analyzedAt":"2026-08-29T20:54:51.419Z","schemaVersion":2},"datasetVersion":"2026-08-29T22:17:34.462Z"}